Omni App-to-App Actions

The strength of Omni’s productivity suite of applications becomes apparent when they interact with each other through the use of Omni Automation. Imagine these scenarios, where through the use of scripts you can:

The following documentation details the use of the Omni Automation functions that enable direct communication between Omni applications. Materials regarding the interaction of Omni application with 3rd-party applications is documented elsewhere on this site.

Script Encoding Functions

Omni Automation uses script URLs to send Omni Automation scripts between its applications and from web-based documentation to its applications. As an example, this website often presents links and buttons that when triggered will execute Omni Automation example scripts on your behalf.

Omni app-to-app scripts incorporate the use of specialized functions that are used to convert a JavaScript function into an Omni Automation script URL that when called will pass the function to the targeted Omni application for execution.

Here are the two functions of the URL class designed to be used for Omni app-to-app communication:

Here is an example of the use of the tellFunction() function:

function targetAppFunction(){console.log("test");return "completed"} var targetAppName = "omnigraffle" var scriptURL = URL.tellFunction(targetAppName, targetAppFunction) console.log(scriptURL)

 1  The JavaScript function to be executed by the targeted application. In this example the function code simply logs an entry to the targeted app’s console and returns the text value: completed

 2  The lowercase name of the Omni application to execute the passed function.

 3  A script URL is generated using the tellFunction() function of the URL class. The targeted app name and the name of the function are passed into the function as its parameters.

 4  The resulting script URL object is logged to the console.

 5  The script URL object, which also reveals the URL string. Note that the resulting encoded function is automatically suffixed with with an open and close pair of parens “( );” which will cause the function to be executed when the script is passed to the target Omni application.

The call() Function

Once the script URL has been generated by the tellFunction() function, the call() function is used to send the script to the targeted Omni application for execution. In addition, the call() function adapts the script URL to include an x-callback-url that returns the script result (or error) to the originating application for processing.

Here is an example of using the call() function without the optional error handling:

function targetAppFunction(){console.log("test");return "completed"} var targetAppName = "omnigraffle" var scriptURL = URL.tellFunction(targetAppName, targetAppFunction) scriptURL.call(function(reply){ // PROCESS RESULTS OF SCRIPT if (typeof reply === "object"){ reply = reply["result"] } console.log(reply) })

 1  The JavaScript function to be executed by the targeted application. In this example the function code simply logs an entry to the targeted app’s console and returns the text value: completed

 2  The lowercase name of the Omni application to execute the passed function.

 3  A script URL is generated using the tellFunction() function of the URL class. The targeted app name and the name of the function are passed into the function as its parameters.

 4  The call() function is executed with the URL instance with a single call-back function as the sole parameter for the function. Any result returned by the executed script will be passed into the call-back function as its parameter.

 6  The script result is logged in the originating app’s console. In this example, a successful script execution will return the string: completed

IMPORTANT: For a successful reply, if the result object has one property, its value is passed as the first argument to the success function. If there are zero or more than one parameters, the full object is passed as the first argument. In both cases, the success function is passed a second argument that is the full object of parameters.

function targetAppFunction(){console.log("test");return "completed"} var targetAppName = "omnigraffle" var scriptURL = URL.tellFunction(targetAppName, targetAppFunction) scriptURL.call(function(reply){ // PROCESS RESULTS OF SCRIPT if (typeof reply === "object"){reply = reply["result"]} console.log(reply) }, function(err){ // PROCESS SCRIPT ERROR new Alert("SCRIPT ERROR", err.errorMessage).show() console.error(err) })

 1  The JavaScript function to be executed by the targeted application. In this example the function code simply logs an entry to the targeted app’s console and returns the text value: completed

 2  The lowercase name of the Omni application to execute the passed function.

 3  A script URL is generated using the tellFunction() function of the URL class. The targeted app name and the name of the function are passed into the function as its parameters.

 4  The call() function is executed on the URL instance with two call-back functions as the parameters for the function. The first call-back function will handle the result of the executed function, and the second function  7  will handle any errors occurring during the execution of the passed function.

 6  The script result is logged in the originating app’s console. In this example, a successful script execution will return the string: completed

 9  Should an error occur during the execution of the passed function, the error message will be displayed in an alert in the originating application.

 10  Log the error message in the host application’s console.

The tellFunction() Function

The tellFunction() function of the URL class provides a very efficient mechanism for performing actions in another Omni application, and optionally returning the results of those actions back to the Omni application originating the Omni Automation app-to-app script.

To use this function, you include a JavaScript function for the targeted Omni application, in the Omni Automation action script for the Omni application hosting the action. The tellFunction() function in your hosted action will automatically convert the included target function into a percent-encoded string that will be included in a script URL executed by the call() function of the URL class. The encoded script will be translated and the passed function executed by the targeted Omni application. Optionally, any results of the function can be returned to the originating application for further use by the hosted script.

In addition, the passed function has the option to receive input through the inclusion of a single passed-in argument that may be either a string, number, date, array, or object. The only requirement for the passed argument is that it be compatible with the JSON.stringify() function, which is how the passed function arguments are made ready for inclusion in the script URL generated by the tellFunction() method.

In the following example action, which targets the OmniOutliner application from any of the other Omni apps, the tellFunction() function is used to pass a function (that will be executed in OmniOutliner) that has no input argument. Note that the result of the passed function (line 20: in this example, a simple message) is returned to the originating script for processing.

In the example, the passed function simply logs a message in the targeted application’s console and returns a message to the originating script, that logs the returned message in the originating app’s console.

Note that the passed function in the example action incorporates the use of the try, catch, and throw statements in order to return an error message to the originating application. Any error message is processed by the second call-back function parameter in the call() function.

/*{ "type": "action", "targets": ["omnigraffle","omnifocus","omniplan"], "author": "Otto Automator", "identifier": "com.omni-automation.ex.tellfunction", "version": "1.1", "description": "A testing script for the tellFunction() function of the URL class", "label": "tellFunction()", "shortLabel": "tellFunction()" }*/ (() => { var action = new PlugIn.Action(function(selection, sender){ // action code var targetAppName = "omnioutliner" // THE FUNCTION TO BE EXECUTED ON THE TARGET APP function targetAppFunction(){ try { // SCRIPT CODE TO EXECUTE console.log("Passed function has been executed") return "completed" } catch(error){ console.error("An error occurred.") throw error } } // CREATE SCRIPT URL WITH FUNCTION var scriptURL = URL.tellFunction( targetAppName, targetAppFunction, null ) // CALL THE SCRIPT URL, PROCESS RESULTS OR ERROR scriptURL.call(function(reply){ // PROCESS RESULTS OF SCRIPT if (typeof reply === "object"){ reply = reply["result"] } console.log(reply) }, function(err){ // PROCESS SCRIPT ERROR new Alert("SCRIPT ERROR", err.errorMessage).show() console.error(error) }) }); action.validate = function(selection, sender){ // validation code return true }; return action; })();

(⬇ see below ) The OmniOutliner console after the action has been run:

omnioutliner-console-01

(⬇ see below ) The OmniFocus console after the action has been run:

omnifocus-console-01

The tellFunction() Function: Object Argument

With the tellFunction() method, the passed function has the option to receive input (before it is passed) through the inclusion of a single passed-in argument that may be either a string, number, date, array, or object. The only requirement for the passed argument is that it be compatible with the JSON.stringify() function, which is how the passed function arguments are made ready for inclusion in the script URL generated by the tellFunction() method.

In many actions implementing a passed data argument, the data is generated dynamically by the script and may represent the contents of objects and elements in the document of the host application.

In the following example, the argument for the passed function is a JavaScript object containing a series of key:value data pairs, with the values being: a string, a number, and an array of strings (lines 18—23). The created object is then added as the last parameter of the tellFunction() function. (line 39)

Note that the passed function in the example action incorporates the use of the try, catch, and throw statements in order to return an error message to the originating application. Any error message is processed by the second call-back function parameter in the call() function.

/*{ "type": "action", "targets": ["omnigraffle","omnifocus","omniplan"], "author": "Otto Automator", "identifier": "com.omni-automation.ex.tellfunction-object", "version": "1.1", "description": "A testing script for the tellFunction() function of the URL class", "label": "tellFunction(object)", "shortLabel": "tellFunction(object)" }*/ (() => { var action = new PlugIn.Action(function(selection, sender){ // action code var targetAppName = "omnioutliner" // OPTIONAL ARGUMENT MAY BE: string, number, date, array, or object var targetFunctionArgument = { "stringValueKey": "HOW NOW BROWN COW", "numericValueKey": 1234, "arrayValueKey": ["Sal","Sue","Carl","Wanda"], "dateValueKey": new Date() } // THE FUNCTION TO BE EXECUTED ON THE TARGET APP function targetAppFunction(arg){ try { var stringValue = arg["stringValueKey"] console.log(stringValue) var numericValue = arg["numericValueKey"] console.log(numericValue) var arrayValue = arg["arrayValueKey"] arrayValue.forEach(item => { console.log(item) }) var dateValueString = arg["dateValueKey"] console.log(Date(dateValueString)) return "completed" } catch(error){ console.error("An error occurred.") throw error } } // CREATE SCRIPT URL WITH FUNCTION var scriptURL = URL.tellFunction( targetAppName, targetAppFunction, targetFunctionArgument ) // CALL THE SCRIPT URL, PROCESS RESULTS OR ERROR scriptURL.call(function(reply){ // PROCESS RESULTS OF SCRIPT if (typeof reply === "object"){ reply = reply["result"] } console.log(reply) }, function(err){ // PROCESS SCRIPT ERROR new Alert("SCRIPT ERROR", err.errorMessage).show() console.error(err) }) }); action.validate = function(selection, sender){ // validation code return true }; return action; })();

(⬇ see below ) The OmniOutliner console showing logs of the passed data:

app-to-app-tellfunction-oo

(⬇ see below ) The console showing the resulting message of the action:

omnifocus-console-01

Copy Selected OmniFocus Tasks to OmniPlan

In the following example, data is gathered about the selected OmniFocus tasks and then set to OmniPlan to recreate the tasks in the current project. In this case, the argument for the passed function is a JavaScript array of JavaScript objects, with each object containing the specifics of a selected OmniFocus task. The transfered data is then processed in sequence to construct new tasks in OmniPlan.

(Requires OmniFocus 3.7 or newer)

Here is the example plug-in:

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.of.op.copy-tasks-to-omniplan", "version": "1.0", "description": "This action will create copies of the selected tasks in the current OmniPlan project.", "label": "Copy Selected Tasks to OmniPlan", "shortLabel": "Copy to OmniPlan" }*/ (() => { var action = new PlugIn.Action(function(selection, sender){ // action code // selection options: tasks, projects, folders, tags var now = new Date() var today = Calendar.current.startOfDay(now) var targetFunctionArgument = new Array() selection.tasks.forEach(function(OFtask){ var OFtaskTitle = OFtask.name var OFtaskID = OFtask.id.primaryKey var OFtaskLink = "omnifocus:///task/" + OFtaskID var OFtaskNote = OFtask.note if (OFtaskNote){ OFtaskNote = (OFtaskNote.length > 0) ? OFtaskNote + "\n" + OFtaskLink : OFtaskLink } else { OFtaskNote = OFtaskLink } var OFtaskDueDate = OFtask.dueDate OFtaskDueDate = (OFtaskDueDate != null) ? OFtaskDueDate : today // CREATE TASK DATA OBJECT var taskDataObj = { "OFtaskTitle":OFtaskTitle, "OFtaskNote":OFtaskNote, "OFtaskDueDate":OFtaskDueDate } targetFunctionArgument.push(taskDataObj) }) console.log(JSON.stringify(targetFunctionArgument)) function targetAppFunction(arg){ try { var OPTaskLinks = new Array() arg.forEach(taskDataObj => { OPtask = actual.rootTask.addSubtask() OPtaskLink = "omniplan:///task/" + OPtask.uniqueID OPtask.title = taskDataObj["OFtaskTitle"] OPtask.note = taskDataObj["OFtaskNote"] OPtask.endNoLaterThanDate = new Date(taskDataObj["OFtaskDueDate"]) OPTaskLinks.push(OPtaskLink) }) return OPTaskLinks } catch(error){ console.log("An error occurred.") throw error } } var scriptURL = URL.tellFunction( "omniplan", targetAppFunction, targetFunctionArgument ) scriptURL.call(function(result){ // PROCESS RESULTS OF SCRIPT console.log("targetAppFunction result: ", result) var selectedTasks = selection.tasks result.forEach((OPTaskLink, index) => { var OFTask = selectedTasks[index] var OFTaskNote = OFTask.note if (OFTaskNote){ if(OFTaskNote.length > 0){ OFTask.note = OFTaskNote + "\n" + OPTaskLink } else { OFTask.note = OPTaskLink } } else { OFTask.note = OPTaskLink } }) }, function(error){ // PROCESS SCRIPT ERROR new Alert("SCRIPT ERROR", error).show() console.error(error) }) }); action.validate = function(selection, sender){ // validation code // selection options: tasks, projects, folders, tags return (selection.tasks.length > 0) }; return action; })();
UNDER CONSTRUCTION

This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.

DISCLAIMER