Triggers: Difference between revisions

From Memento Database Wiki
Jump to navigation Jump to search
No edit summary
 
(479 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Stamp|2016-09-09|4.0.0|1.0.5}}
{{Stamp|2023-08-12|5.0|2.0}}
{{BannerMenu}}
{{PageTitle|Triggers}}


Триггер это скрипт, который запускается при определенных действиях или событиях. В качестве языка для написания скриптов используется '''[https://developer.mozilla.org/en-US/docs/Web/JavaScript JavaScript]'''. Результатом выполнения скрипта может быть изменение или создание записи, выполнение http-запроса, создание файла, валидация данных и другие действия.
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.
-----


== Создание триггера ==
== Definitions ==
Каждая библиотека может иметь несколько триггеров, чтобы открыть список триггеров зайдите в библиотеку, откройте меню и выберите пункт '''Триггеры'''.
We define the following terms:
:; Event type
:: One of the following:
::* Opening a library
::* Creating an entry
::* Updating an entry
::* Updating a field
::* Deleting an entry
::* Linking an entry
::* Unlinking 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 [[#Events & Phases|the table of events and phases below]].<br/> 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<br/>The trigger (Event type & Phase) and the corresponding trigger script are one-to-one.<br/>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 &mdash; 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()''.<br/>Time-consuming operations are not recommended in this mode.
Некоторые функции доступные из скриптов (операции с файлами, выполнение http-запросов, доступ к другим библиотекам) в целях безопасности требуют соответствующих разрешений.  
Эти разрешения пользователь должен установить вручную для каждой библиотеки отдельно.


Чтобы открыть диалог установки разрешений для скриптов - откройте список триггеров библиотеки и нажмите кнопку '''Щит''' на тулбаре. Установка разрешений должна выполняться на каждом устройстве отдельно. Выбранные разрешения не синхронизируются между устройствами.
:; 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.
-----
=== 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 ==
; Libraries : Определяет какие библиотеки помимо родной будут доступны скрипту. Вы можете предоставить доступ ко всем библиотекам или выбрать определенные библиотеки. Данное разрешение требуется для функции libByName.
These are the defined ''Event types'', ''Phases'', and their corresponding modes of execution.
; Read files : Предоставляет скрипту доступ на чтение файлов с запоминающего устройства. Данное разрешение требуется для функции file.
{| class="wikitable" style="font-size:120%"
; Write files : Предоставляет скрипту доступ на создание и изменение файлов в запоминающем устройстве. Данное разрешение требуется для функции file.
|+ THE DEFINED EVENT TYPES & THEIR PHASES
; Network : Предоставляет скрипту право выполнять http запросы. Данное разрешение требуется для функции http.
|-
 
! Event type !! Phase !! [[#Mode of script execution|Execution mode]]
== Действия ==
|-
{| class="wikitable"
|| '''[[#Opening a library|Opening a library]]'''
| '''Opening the library''' || synchronous
|-
| rowspan="3" | '''[[#Creating an entry|Creating an entry]]'''
| '''Opening an Entry Edit card''' || synchronous
|-
| '''Before saving the entry'''  || synchronous
|-
| '''After saving the entry''' || asynchronous
|-
|-
! Действие !! Фаза !! Выполнение
| rowspan="3" | '''[[#Updating an entry|Updating an entry]]'''
| '''Opening an Entry Edit card''' || synchronous
|-
|-
| rowspan="3" | Создание записи
| '''Before saving the entry''' || synchronous
| открытие формы создания || синхронное
|-
|-
| перед сохранением записи  || синхронное
| '''After saving the entry''' || asynchronous
|-
|-
| после сохранения записи || асинхронное
| rowspan="2" | '''[[#Linking an entry|Linking an entry]]'''
| '''Before saving the entry'''  || synchronous
|-
|-
| rowspan="3" | Изменение записи
| '''After saving the entry''' || asynchronous
| открытие формы изменения записи || синхронное
|-
|-
| перед сохранением записи || синхронное
| rowspan="2" | '''[[#Unlinking an entry|Unlinking an entry]]'''
| '''Before saving the entry''' || synchronous
|-
|-
|после сохранения записи || асинхронное
| '''After saving the entry''' || asynchronous
|-
|-
| rowspan="2" | Удаление записи
| rowspan="2" | '''[[#Deleting an entry|Deleting an entry]]'''
| перед удалением записи || синхронное
| '''Before deleting the entry''' || synchronous
|-
|-
| после удаления записи || асинхронное
| '''After deleting the entry''' || asynchronous
|-
|-
| rowspan="2" | Открытие карточки записи
| rowspan="2" | '''[[#Opening an Entry View card|Opening an Entry View card]]'''
| перед отображением окна || синхронное
| '''Before window display''' || synchronous
|-
|-
| после отображения окна || асинхронное
| '''After window display''' || asynchronous
|-
|-
| rowspan="2" | Добавление записи в избранное
| rowspan="2" | '''[[#Adding an entry to Favorites|Adding an entry to Favorites]]'''
| перед операцией || синхронное
| '''Before the operation''' || synchronous
|-
|-
| после операции || асинхронное
| '''After the operation''' || asynchronous
|-
|-
| rowspan="2" | Удаление записи из избранного
| rowspan="2" | '''[[#Removing an entry from Favorites|Removing an entry from Favorites]]'''
| перед операцией || синхронное
| '''Before the operation''' || synchronous
|-  
|-  
| после операции || асинхронное
| '''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 ===
This event starts when a user has requested that a new entry be added to the library, normally by pressing the '''<big>+</big>''' button on the Entries List screen. It ends after the entry is saved to storage &mdash; 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.<br/>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.<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.
 
:; 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 ====


====entry()====
'''=>''''' Say what here? '''''
:Получить запись в контексте которой происходит выполнение скрипта. Т.е. если скрипт выполняется на действие Изменение записи, то данная функция возвращает изменяемую запись.
:Функция доступа для всех действий и фаз выполнения, за исключением "Создание записи - открытие формы создания", для данного действия используйте функцию entryDefault.


:Результат: Объект Entry, текущая запись.
===== 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.


====entryDefault()====
Use the method ''defaultEntry()'', rather than ''entry()'', to get the DefaultEntry object (the ''un''stored template, if you will, for the eventual Entry object).
:Получить объект для установки значений по умолчанию для еще не созданной записи. Функция доступна для действия ''Создание записи'' и фазы выполнения ''Открытие формы создания''.


:Результат: Объект DefaultEntry.
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()''.


====lib()====  
=== 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 &mdash; 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.


:Результат: Объект Library, текущая библиотека.
:; 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.<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.


====libByName(name)====
:; 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.
:Найти библиотеку по имени. В настройках безопасности должно быть установлено разрешение на использование получаемой библиотеки.


:Результат: Объект Library, найденная библиотека.
'''<i><b>The following 2 sections are under development.</b></i>'''


===Объект Library===
=== Updating a field ===
Через этот объект осуществляется доступ к записям библиотеки. Можно работать с текущей библиотекой - ''lib()'' или с любой другой библиотекой в базе данных - ''libByName()''. Помимо функций получения записей данный объект предоставляет возможность создания новой записи.
TBD
====Методы====
=====entries()=====
:Получить все записи библиотеки.
:Результат: Array[Entry] Массив записей. Записи отсортированы по времени их создания - от новых к старым.


=====find(query)=====
=== Linking an entry ===
:Поиск записей в библиотеки по значениям полей. Поиск аналогичен [[Working with library entries#EntrySearch|поиску через интерфейс]] программы.
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.
:Параметры: query - строка поиска.  
==== Phases ====
:Результат: Array[Entry] Массив найденных записей. Записи отсортированы по времени их создания - от новых к старым.
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.


=====findByKey(name)=====
:; 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.
:Поиск записи в библиотеки по имени. Для библиотеки должен быть включен параметр ''Уникальные имена''.
:Параметры: name - имя записи.
:Результат: Объект Entry.


=====create(values)=====
The script of this event type has access to additional functions:
:Создание новой записи в библиотеке.
===== masterLib() =====
:Параметры: values - объект класса [https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object'''Object'''] содержащий значения полей.
:Returns the library from which the current record was referenced.
:Результат: Объект Entry, созданная запись.
===== 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 ===
;title : Название библиотеки.
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.


===Объект Entry===
:; 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.
Этот объект является записью библиотеки и предоставляет возможность получать и устанавливать значения полей.
====Методы====
=====set(name , value)=====
:Установить значение поля. После вызова метода сразу же происходит запись значения в базу данных.
:Параметры: name - имя поля, value - значение поля.


=====field(name)=====
=== 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 &mdash; or else not, depending on the processing of the entry.
:Параметры: name - имя поля
:Результат: значение поля, тип результата зависит от типа поля.


====Свойства====
==== Phases ====
;title : Имя записи.
This event has two phases. In sequence:
;description : Описание записи.
:; 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.<br/>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.<br/>Mainly, help the user reconfirm that the deletion should take place, and if not, call ''cancel()'' and inform the user (via ''message()'').
;favorites : Возвращает true - если запись находится в избранном
;deleted : Возвращает true - если запись удалена (находится в корзине).


===Объект DefaultEntry===
:; 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.<br/> Anything you want to do whenever an entry is deleted should be done in this script.
Шаблон со значениями по умолчанию для создания новой записи.
====Методы====
=====set(name , value)=====
:Установить значение поля.  
:Параметры: name - имя поля, value - значение поля.


===Примеры===
=== 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.<br/>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.<br/>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.
Все операции с файлами производятся через объект File, который получается через вызов метода file().
==== 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.<br/>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.<br/>This action could be logged, for instance, or it could trigger an action on some other app.


Для работы с файлами для библиотеки должно быть установлено разрешение - на чтение и/или на запись файлов.
-----
===Глобальные Функции===
<br/>
====file(name)====
Открыть файл для операций чтения или записи.
:Параметр: name - имя и полный путь к файлу. Например, если файл расположен на sd-card, путь должен иметь вид /sdcard/example.txt.
:Результат: Объект File.


===Объект File===
== Security ==
Данный объект возвращается функцией file() и предоставляет доступ к запрошенному файлу.  Если файл с указанным в функции file() именем ещё не существует, то но будет создан. После операций чтения или записи файл должен быть закрыть функцией close().
Since the scripts have access to more actions than a user does, they require additional permissions.
====Методы====
=====readAll()=====
:Reads all lines of the file, and then closes the file.
=====readLine()=====
:Read a line.
=====readLines()=====
:Read the remaining lines in the file and return them in an array.
=====readChar()=====
:Read a character.
=====write(text)=====
:Write strings. This function takes a variable number of arguments, converts each argument to a string, and writes that string to the file.
=====writeLine(text)=====
:Write strings and a newline.
=====close()=====
:Close the file. It may be reopened.
====Свойства====
; exists : true - if and only if the file denoted by this object exists; false otherwise
; length : The length, in bytes, of the file denoted by this object, or 0L if the file does not exist.
; getLineNumber : Get the current line number.


===Примеры===
The user must define these permissions manually for each library.
====Запись и чтение из файла====
<source lang="javascript" line>
f= file("/sdcard/myfile.txt")
file.writeLine("one");                     
file.writeLine("two");
file.writeLine("three");
file.close();   
var a = file.readLines();
</source>


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.


==Выполнение http запросов==
=== Permissions for scripts ===
С помощью скриптов можно выполнять http-запросы, что позволяет обмениваться информацией с веб-службами предоставляющими API. Также через http запросы вы можете интегрировать Memento со своей системой.
:; Library permission
Все операции с файлами производятся через объект Http, который получается через вызов глобального метода http().
:: 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.


Http запросы доступны при соблюдении двух условий:
:; Read permission
# Выполнение скрипта должно быть асинхронным (фоновым), так как обработка запроса по сети может занимать много времени. Таким образом выполнять http-запросы можно только в последних фазах действий.
:: grants the script read access to a file
# В библиотеки должно быть установлено разрешение - Network.
===Объект Http===
Интерфейс выполнения http запросов.
====Методы====
=====get(url)=====
:Выполнить get запрос.
:Параметры: url - http адрес, должен начинаться с http или https
:Результат: HttpResult - объект содержащий результат выполнения http запроса.


===Объект HttpResult===
:; Write permission
Результат выполнения http запроса
:: grants the script write access to a file
====Свойства====
;code : http код ответа, если запрос выполнен успешно, то он обычно равен 200.
;body : тело ответа в виде текста.


===Примеры===
:; Network
====Конвертация валюты====
:: grants to the script the right to execute HTTP requests
Библиотека содержит два поля PriceUSD и PriceEUR. Пользователь заполняет только поле PriceUSD, требуется чтобы в поле  PriceEUR  записывалась цена в евро по текущему курсу.
-----
Создадим триггер на действие ''Создание записи'', фаза выполнения будет ''После сохранения''.
<br/>
<source lang="javascript" line>
result = http().get("http://api.fixer.io/latest?base=USD")
usdToEur = JSON.parse(result.body)["rates"]["Eur"]
entry().set("PriceEUR" , entry().field( "PriceUSD") * usdToEur )
</source>
#Для получения курсов валют пользуемся сервисом http://fixer.io/. Сервис по запросу http://api.fixer.io/latest?base=USD возвращает курсы валют в JSON формате.
#Воспользуется стандартным JavaScript объектом JSON чтобы распарсить ответ.
#Умножаем цену из поля PriceUSD на коэффициент конвертации валюты и устанавливаем полученное значение в поле PriceEUR.


====Создание задачи в приложении Todoist====
== Creating a trigger ==
[https://todoist.com Todoist] — это веб-сервис и программа для управления задачами. Веб-сервис предоставляет возможность через [https://developer.todoist.com/ api] создавать задачи.
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''.
Приведем скрипт для создания задачи, текст задачи будет браться из записи.  
<source lang="javascript" line>
var commands='[{"uuid":"' + guid() + '","temp_id":"' + guid() + '","type":"item_add","args":{"content":"' + entry().field("Task") + '"}}]'
result = http().get("https://todoist.com/API/v7/sync?token=15281e8e4d499dаff817af0b14112eac3176f9dc&commands=" + encodeURIComponent(commands))
if (result.code == 200) message('Task has been successfully created")
</source>
#Составляем команду в json формате для создания задачи в todoist, формат команды описан здесь: https://developer.todoist.com/#add-an-item. В команде должны присутствовать уникальные идентификаторы, для их получения используем глобальную функцию guid().
#Выполняем http запрос. Атрибут token используется для авторизации в todoist, его можно получить в Настройках Todoist вкладка Аккаунт. Так как текст задачи может содержать символы недопустимые в URL-запроса, то экранируем их с помощью стандартной функции encodeURIComponent().
#Выводим пользователю сообщение об успешно созданной задачи.


==Взаимодействие с системой==
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 <big>'''+'''</big>. You must then identify the Event type & Phase and write a trigger script that performs the necessary actions.
===Глобальные Функции===
====message(text)====
:Отобразить пользователю небольшое всплывающее сообщение.
:Параметры: text - текст для отображения.


====cancel()====
=== Writing a Trigger Script ===
:Отменить операцию вызвавшую данный триггер. Многие действия возникают при каких либо операциях с записями (создание, модификация, удаление и .д.). Если фаза действия предшествует операции, то возможно отменить эту операцию с помощью данной функции. Например, применять эту функцию можно при проверки корректности вводимых данных перед сохранением записи.
Trigger scripts are in the JavaScript language. See '''''[[#JavaScript links|Links to JavaScript documentation]]''''' below.


====system()====
; 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.
:Получить информацию о системе.
:Результат: Объект System с информацией о системе.


====log(text)====
; Globals get you started: Note the global functions in the sections below; they generally get you started by providing needed information.
:Вывести строку в лог-файл выполнения скрипта. Функция будет полезна для отладки скриптов.
:Параметры: Text - текст который будет выведен в лог.


====guid()====
; 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()''.
:Генерация случайного текстового идентификатора.
:Результат: Случайная строка-идентификатор.


====intent(action)====
; 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.
:Создать объект обмена сообщениями - Intent. С помощью данного объекта можно передать данные другому приложению, или заставить другое приложение выполнить какое-либо действие.
:Функция доступна только для Android.
:Параметры: action - Строка, определяющая стандартное действие, которое требуется выполнить (например, view (просмотр) или pick (выбор)).
:Результат: Intent - объект обмена сообщениями.
:После получения объекта требуется добавить в него отправляемые данные и вызывать метод send().
:В Android есть множество встроенных  действий, список и описание которых вы можете найти [https://developer.android.com/reference/android/content/Intent.html здесь].


===Объект System===
; Permissions: Certain functions require special permissions; read '''''[[#Security|above]]''''' about that. One such function is ''libByName()''. Others include the file access and HTTP functions.
Данный объект содержит информацию о системе.
====Свойства====
;os : имя операционной системы на которой запущен скрипт.  


===Объект Intent===
; 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.
Объект обмена сообщениями. Объект создается с помощью вызова глобальной функции intent().
====Методы====
=====data(uri)=====
:Установить URI ссылающийся на данные.
:Параметры:uri - URI, ссылающийся на данные, с которыми будет выполняться действие. Это может быть идентификатор контакта, путь к файлу, номер телефона и т.д.
=====mimeType(mime)=====
:Установить MIME тип данных.
:Параметры:mime - MIME тип данных с которыми будет выполняться действие.
=====extra(key, value)=====
:Установить дополнительные данные в виде ключ-значение, которые необходимы для выполнения запрошенного действия. Точно так же, как некоторые действия используют определенные виды URI данных, некоторые действия используют определенные дополнительные данные.
:Параметры:
=====extraLong(key, value)=====
:Установить дополнительные данные в виде ключ-значение, где значение должно быть типом Long.
=====send()=====
:Отправить сообщение.


===Примеры===
==== 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.
В библиотеке должно быть поле Phone, содержащие номер телефона.
:; 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.
<source lang="javascript" line>
-----
i = intent("android.intent.action.DIAL")
<br/>
i.data("tel:"+entry().field("Phone"))
i.send()
</source>
# Создаем объект обмена сообщениями Intent и указываем действие которое откроет окно набора номера - android.intent.action.DIAL.
# В качестве данных требуется указать номер телефона в формате ''tel:номер''. Номер телефона берем из поля записи Phone.
# Отправляем сообщение.


====Скрипт открывающий приложение для отправки смс-сообщения====
== See Also ==
Номер телефона будет определяться полем записи - Phone, а текст сообщения составляется из полей ContactName и Notes.
; [[Memento JavaScript Library]]: Memento JavaScript functions & objects<br/>
<source lang="javascript" line>
; [[Trigger Examples]]: Examples of trigger scripts for common needs
msg = "Dear, " + entry().field("ContactName") + "\n" + entry().field("Notes")
; [[How:Write scripts in JavaScript for Memento]]: Guidelines for writing JavaScript scripts for Memento
i = intent("android.intent.action.SENDTO")
i.data("smsto:"+entry().field("Phone"))
i.extra("sms_body" , msg)
i.send()
</source>
# Составляем сообщение из значений полей ContactName и Notes
# Создаем объект обмена сообщениями Intent и указываем действие которое откроет приложение для отправки сообщений- android.intent.action.SENDTO.
# В качестве данных требуется указать номер телефона в формате ''smsto:номер''. Номер телефона берем из поля записи Phone.
# Текст сообщение передаем в дополнительный параметр sms_body.
# Отправляем сообщение.


====Скрипт открывающий форму создания события в Гугл-Календаре.====
[[Category:en]] [[Category:Spec]] [[Category:Sc]]
Время события и название события будут определяться полями записи.
<source lang="javascript" line>
i = intent("android.intent.action.INSERT")
i.data("content://com.android.calendar/events")
i.extra("title", entry().field("Title"))
i.extra("description" , entry().field("Description"))
i.extraLong("beginTime" , entry().field("Begin").getTime())
i.extraLong("endTime" , entry().field("End").getTime())
i.send()
</source>
# Создаем объект обмена сообщениями Intent и указываем действие которое требуется выполнить, а именно создание объекта - android.intent.action.INSERT.
# Для события android.intent.action.INSERT в data требуется передать базовый Uri создаваемого объекта. Событие в Google-календаре имеет базовый Uri - content://com.android.calendar/events.
# Устанавливаем название события, которое берем из поля Title.
# Устанавливаем описание события, которое берем из поля Description.
# Устанавливаем время начала события, которое берем из поля Begin. Поле Begin должно иметь тип Date/Time. Дополнительный параметр beginTime должен иметь тип Long, поэтому используется метод extraLong.
# Устанавливаем время окончания события, которое берем из поля End. Поле End должно иметь тип Date/Time. Дополнительный параметр endTime должен иметь тип Long, поэтому используется метод extraLong.
# Отправляем сообщение.

Latest revision as of 08:26, 23 August 2023

« Page as of 2023-08-12, editions Mobile 5.0, Desktop 2.0 »

Wiki
Home
About
Wiki | Memento
Getting started
Wiki | Memento
Indexes
Mobile | Desktop | Scripting
Support
Wiki | Memento
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:
  • Opening a library
  • Creating an entry
  • Updating an entry
  • Updating a field
  • Deleting an entry
  • Linking an entry
  • Unlinking 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.

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

These are the defined Event types, Phases, and their corresponding modes of execution.

THE DEFINED EVENT TYPES & THEIR PHASES
Event type Phase Execution mode
Opening a library Opening the library synchronous
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
Linking an entry Before saving the entry synchronous
After saving the entry asynchronous
Unlinking an entry 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

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

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.

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 — the Entry object does not yet exist — so it needs to be handled differently.

Use the method defaultEntry(), rather than entry(), to get the DefaultEntry object (the unstored 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

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.

The following 2 sections are under development.

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 — 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.
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.
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.
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 — 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.
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.
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.
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.


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 in the JavaScript language. 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.


See Also

Memento JavaScript Library
Memento JavaScript functions & objects
Trigger Examples
Examples of trigger scripts for common needs
How:Write scripts in JavaScript for Memento
Guidelines for writing JavaScript scripts for Memento