URL: App-to-App Scripting

A fundamental principle of user-automation is:

No application is an island.

In other words, it is quite appropriate to expect scripts to be able to extract and share data between multiple applications. After all, that’s the way we work, why shouldn’t our automation tools do the same?

To facilitate the sharing of data between Omni applications, a “Call and Response” scenario is implemented in Omni Automation scripts. With “Call and Response” a host application gathers data from another application, and then uses that data in performing actions with its own document and objects. For example, a script executed in OmniGraffle may use the topics from the current OmniOutliner document, to create named text objects in the current OmniGraffle document.

To extract or gather data from another application, the script run by the host application uses either the tellScript() or fromString() methods from the URL class, to generate a new Omni Automation script URL. This script URL is then executed by the host script using the call() method of the URL class, which has as its direct parameter, a call-back function to process the results returned from the Omni Automation URL script. It is important to note that the generated Omni Automation script URL should return some type data (like a string or an array) as its result.

The following materials show how to implement either of the two available techniques for deploying “call and response” automation between applications from the Omni Group.

The Calling Script is Omni Automation Code

The first technique for performing “Call and Response” uses the tellScript() method of the URL class to create a URL object by converting the quoted code of an Omni Automation script into an Omni Automation script URL.

Your app-to-app script begins with a function containing the code you wish to run with the called application (line 1). For example, if your script is designed to create OmniGraffle canvases based upon the topics in the current OmniOutliner document, your calling function would contain the code for retrieving and returning the topics in OmniOutliner document. It is important for this function to return data of some type, such as a string or an array.

Next, your script will create an Omni Automation script URL using the tellScript() method, which takes two parameters:

function titleOfFunction(){ // Omni Automation code for other application } var scriptURL = URL.tellScript("nameOfTargetApp", titleOfFunction.toString() + '\n' + 'titleOfFunction()') scriptURL.call(function(reply){ // CODE FOR DEALING WITH RESULTS OF SCRIPT })

To execute the created script URL, the call() method is applied to the script URL object (line 5 above). This method has a call-back function as its parameter. This call-back function includes the passed result of the script URL execution as its sole parameter. These results are then used by the code in the host script (line 5) when the call-back function gets called.

Using the tellScript() method to perform call and response offers the advantage of providing easy editing of both the calling and response scripts. With this approach, you can quickly alter either script as needed. Below is an example of call and response using the tellScript() method to create the calling script URL.

In the example script below, the calling script (lines 9 - 16) is written as a function that returns the result to be used by the response script. The function is converted into a string (line 18) using the toString() method, and is then appended with a new line placeholder (\n) and the full name of the calling function as a string (be sure to include the open and close parens).

The tellScript() function (line 18) converts the call function text and the appended new line and function name into an encoded Omni Automation URL, that is then executed using the call() function (line 20). The result of the calling script is passed to the response script in the variable “reply” (line 20).

function getTopics(){ var titles = new Array() var items = rootItem.children for (i = 0; i < items.length; i++) { titles[i] = items[i].topic } return titles } getTopics()
var alert = new Alert("Confirmation", "This script will import the topics from the current OmniOutliner document to OmniGraffle as canvas slides.\n\nShould the script continue?") alert.addOption("Continue") alert.addOption("Stop") alert.show(function(result){ if (result == 1){ throw new Error('script cancelled') } else { // calling function for target app function getTopics(){ var titles = new Array() var items = rootItem.children for (i = 0; i < items.length; i++) { titles[i] = items[i].topic } return titles } // use the toString() function to turn the calling function into a string that gets passed to the tellScript() function // concatenate a new line placeholder (\n) and the text of the calling function name (with parens) to the end of the string passed to the tellScript() method var scriptURL = URL.tellScript("omnioutliner", getTopics.toString() + '\n' + 'getTopics()') // execute the script URL scriptURL.call(function(reply){ var aCanvas = document.windows[0].selection.canvas var aCanvasSize = aCanvas.size var cW = aCanvasSize.width var cH = aCanvasSize.height var typeSize = Math.round(cH/cW*100) for (i = 0; i < reply.length; i++){ replyItem = reply[i] if(i != 0){ aCanvas = addCanvas() aCanvas.size = aCanvasSize } aCanvas.name = replyItem aShape = aCanvas.newShape() aShape.text = "<%Canvas%>" // replyItem aShape.autosizing = TextAutosizing.Full aShape.textHorizontalAlignment = HorizontalTextAlignment.Center aShape.textSize = typeSize aShape.shadowColor = null aShape.strokeType = null aShape.strokeColor = null aShapeGeo = aShape.geometry aRect = new Rect(cW/2 - aShapeGeo.width/2, typeSize, aShapeGeo.width, aShapeGeo.height) aShape.geometry = aRect } }) } })
omnigraffle:///omnijs-run?script=var%20alert%20%3D%20new%20Alert%28%22Confirmation%22%2C%20%22This%20script%20will%20import%20the%20topics%20from%20the%20current%20OmniOutliner%20document%20to%20OmniGraffle%20as%20canvas%20slides%2E%5Cn%5CnShould%20the%20script%20continue%3F%22%29%0Aalert%2EaddOption%28%22Continue%22%29%0Aalert%2EaddOption%28%22Stop%22%29%0Aalert%2Eshow%28function%28result%29%7B%0A%09if%20%28result%20%3D%3D%201%29%7B%0A%09%09throw%20new%20Error%28%27script%20cancelled%27%29%0A%09%7D%20else%20%7B%0A%09%09function%20getTopics%28%29%7B%0A%09%09%09var%20titles%20%3D%20new%20Array%28%29%0A%09%09%09var%20items%20%3D%20rootItem%2Echildren%0A%09%09%09for%20%28i%20%3D%200%3B%20i%20%3C%20items%2Elength%3B%20i%2B%2B%29%20%7B%0A%09%09%09%09titles%5Bi%5D%20%3D%20items%5Bi%5D%2Etopic%0A%09%09%09%7D%0A%09%09%09return%20titles%0A%09%09%7D%0A%09%09var%20scriptURL%20%3D%20URL%2EtellScript%28%22omnioutliner%22%2C%20getTopics%2EtoString%28%29%20%2B%20%27%5Cn%27%20%2B%20%27getTopics%28%29%27%29%0A%09%09scriptURL%2Ecall%28function%28reply%29%7B%0A%09%09%09var%20aCanvas%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09%09var%20aCanvasSize%20%3D%20aCanvas%2Esize%0A%09%09%09var%20cW%20%3D%20aCanvasSize%2Ewidth%0A%09%09%09var%20cH%20%3D%20aCanvasSize%2Eheight%0A%09%09%09var%20typeSize%20%3D%20Math%2Eround%28cH%2FcW*100%29%0A%09%09%09for%20%28i%20%3D%200%3B%20i%20%3C%20reply%2Elength%3B%20i%2B%2B%29%7B%0A%09%09%09%09replyItem%20%3D%20reply%5Bi%5D%0A%09%09%09%09if%28i%20%21%3D%200%29%7B%0A%09%09%09%09%09aCanvas%20%3D%20addCanvas%28%29%0A%09%09%09%09%09aCanvas%2Esize%20%3D%20aCanvasSize%0A%09%09%09%09%7D%0A%09%09%09%09aCanvas%2Ename%20%3D%20replyItem%0A%09%09%09%09aShape%20%3D%20aCanvas%2EnewShape%28%29%0A%09%09%09%09aShape%2Etext%20%3D%20%22%3C%25Canvas%25%3E%22%20%2F%2F%20replyItem%0A%09%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EFull%0A%09%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ECenter%0A%09%09%09%09aShape%2EtextSize%20%3D%20typeSize%0A%09%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09%09aShape%2EstrokeColor%20%3D%20null%0A%09%09%09%09aShapeGeo%20%3D%20aShape%2Egeometry%0A%09%09%09%09aRect%20%3D%20new%20Rect%28cW%2F2%20-%20aShapeGeo%2Ewidth%2F2%2C%20typeSize%2C%20aShapeGeo%2Ewidth%2C%20aShapeGeo%2Eheight%29%0A%09%09%09%09aShape%2Egeometry%20%3D%20aRect%0A%09%09%09%7D%0A%09%09%7D%29%0A%09%7D%0A%7D%29

When the script example (shown above) is executed, a new canvas will be created in OmniGraffle for each of the topics in the OmniOutliner document. In addition, the title of the topic will be displayed on the new canvas, centered horizontally at the top.

TIP: Note that instead of entering the topic into the created text field (line 34) the OmniGraffle document variable <%Canvas%> is used instead. This wil cause the name of the canvas to be displayed in the created text box. Since the script names each canvas for a topic, the created text box will also display the topic as well.

The Calling Script is an Omni Automation URL String

The second technique for implementing “Call and Response” in an Omni Automation script, it to use the fromString() method of the URL class to convert an encoded Omni Automation script URL string into a URL object, and then execute the script URL object using the call() method of the URL class as in the previous example.

TIP: For detailed information about creating Omni Automation links, vist this webpage.

var scriptURL = URL.fromString(' // ENCODED SCRIPT URL TO BE EXECUTED BY TARGET APP ') scriptURL.call(function(reply){ // CODE FOR DEALING WITH RESULTS OF SCRIPT })

In the script outline shown above, the percent-encoded script URL string is entered as the direct parameter of the fromString() method. This method creates a new URL object from the script URL string.

To execute the created script URL object, the call() method is applied to the script URL object (line 4 above). This method has a call-back function as its parameter. This call-back function includes the passed result of the script URL execution as its sole parameter. These results are then used by the code in the host script (line 5) when the call-back function gets called.

Below is an example of call and response using the fromString() method of the URL class to create the calling script URL object.

function getTopics(){ var titles = new Array() var items = rootItem.children for (i = 0; i < items.length; i++) { titles[i] = items[i].topic } return titles } getTopics()
var alert = new Alert("Confirmation", "This script will import the topics from the current OmniOutliner document to OmniGraffle as canvas slides.\n\nShould the script continue?") alert.addOption("Continue") alert.addOption("Stop") alert.show(function(result){ if (result == 1){ throw new Error('script cancelled') } else { var scriptURL = URL.fromString('omnioutliner:///omnijs-run?script=function%20getTopics%28%29%7B%0A%09var%20titles%20%3D%20new%20Array%28%29%0A%09var%20items%20%3D%20rootItem%2Echildren%0A%09for%20%28i%20%3D%200%3B%20i%20%3C%20items%2Elength%3B%20i%2B%2B%29%20%7B%0A%09%09titles%5Bi%5D%20%3D%20items%5Bi%5D%2Etopic%0A%09%7D%0A%09return%20titles%0A%7D%0AgetTopics%28%29') scriptURL.call(function(reply){ var aCanvas = document.windows[0].selection.canvas var aCanvasSize = aCanvas.size var cW = aCanvasSize.width var cH = aCanvasSize.height var typeSize = Math.round(cH/cW*100) for (i = 0; i < reply.length; i++){ replyItem = reply[i] if(i != 0){ aCanvas = addCanvas() aCanvas.size = aCanvasSize } aCanvas.name = replyItem aShape = aCanvas.newShape() aShape.text = "<%Canvas%>" // replyItem aShape.autosizing = TextAutosizing.Full aShape.textHorizontalAlignment = HorizontalTextAlignment.Center aShape.textSize = typeSize aShape.shadowColor = null aShape.strokeType = null aShape.strokeColor = null aShapeGeo = aShape.geometry aRect = new Rect(cW/2 - aShapeGeo.width/2, typeSize, aShapeGeo.width, aShapeGeo.height) aShape.geometry = aRect } }) } })
omnigraffle:///omnijs-run?script=var%20alert%20%3D%20new%20Alert%28%22Confirmation%22%2C%20%22This%20script%20will%20import%20the%20topics%20from%20the%20current%20OmniOutliner%20document%20to%20OmniGraffle%20as%20canvas%20slides%2E%5Cn%5CnShould%20the%20script%20continue%3F%22%29%0Aalert%2EaddOption%28%22Continue%22%29%0Aalert%2EaddOption%28%22Stop%22%29%0Aalert%2Eshow%28function%28result%29%7B%0A%09if%20%28result%20%3D%3D%201%29%7B%0A%09%09throw%20new%20Error%28%27script%20cancelled%27%29%0A%09%7D%20else%20%7B%0A%09%09var%20scriptURL%20%3D%20URL%2EfromString%28%27omnioutliner%3A%2F%2F%2Fomnijs-run%3Fscript%3Dfunction%2520getTopics%2528%2529%257B%250A%2509var%2520titles%2520%253D%2520new%2520Array%2528%2529%250A%2509var%2520items%2520%253D%2520rootItem%252Echildren%250A%2509for%2520%2528i%2520%253D%25200%253B%2520i%2520%253C%2520items%252Elength%253B%2520i%252B%252B%2529%2520%257B%250A%2509%2509titles%255Bi%255D%2520%253D%2520items%255Bi%255D%252Etopic%250A%2509%257D%250A%2509return%2520titles%250A%257D%250AgetTopics%2528%2529%27%29%0A%09%09scriptURL%2Ecall%28function%28reply%29%7B%0A%09%09%09var%20aCanvas%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09%09%09var%20aCanvasSize%20%3D%20aCanvas%2Esize%0A%09%09%09var%20cW%20%3D%20aCanvasSize%2Ewidth%0A%09%09%09var%20cH%20%3D%20aCanvasSize%2Eheight%0A%09%09%09var%20typeSize%20%3D%20Math%2Eround%28cH%2FcW*100%29%0A%09%09%09for%20%28i%20%3D%200%3B%20i%20%3C%20reply%2Elength%3B%20i%2B%2B%29%7B%0A%09%09%09%09replyItem%20%3D%20reply%5Bi%5D%0A%09%09%09%09if%28i%20%21%3D%200%29%7B%0A%09%09%09%09%09aCanvas%20%3D%20addCanvas%28%29%0A%09%09%09%09%09aCanvas%2Esize%20%3D%20aCanvasSize%0A%09%09%09%09%7D%0A%09%09%09%09aCanvas%2Ename%20%3D%20replyItem%0A%09%09%09%09aShape%20%3D%20aCanvas%2EnewShape%28%29%0A%09%09%09%09aShape%2Etext%20%3D%20%22%3C%25Canvas%25%3E%22%20%2F%2F%20replyItem%0A%09%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EFull%0A%09%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ECenter%0A%09%09%09%09aShape%2EtextSize%20%3D%20typeSize%0A%09%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09%09aShape%2EstrokeColor%20%3D%20null%0A%09%09%09%09aShapeGeo%20%3D%20aShape%2Egeometry%0A%09%09%09%09aRect%20%3D%20new%20Rect%28cW%2F2%20-%20aShapeGeo%2Ewidth%2F2%2C%20typeSize%2C%20aShapeGeo%2Ewidth%2C%20aShapeGeo%2Eheight%29%0A%09%09%09%09aShape%2Egeometry%20%3D%20aRect%0A%09%09%09%7D%0A%09%09%7D%29%0A%09%7D%0A%7D%29

Here’s a short video demonstrating App-to-App scripting between OmniGraffle and OmniOutliner (iOS). In the shown example, the topics from an OmniOutliner document are used to create “slides” in the current OmniGraffle document.

App Switcher Scripts

Here’s a simple but useful example of app-to-app scripting: creating an app-switcher script. Using the activate() method of the application class, and the call() method of the URL class, here are short scripts you can use to quickly switch between Omni applications. They make great Toolbar actions!

scriptURL = URL.fromString('omnioutliner://localhost/omnijs-run?script=app.activate()') scriptURL.call(function(reply){})
omnioutliner:///omnijs-run?script=scriptURL%20%3D%20URL%2EfromString%28%27omnioutliner%3A%2F%2Flocalhost%2Fomnijs-run%3Fscript%3Dapp%2Eactivate%28%29%27%29%0AscriptURL%2Ecall%28function%28reply%29%7B%7D%29
url = URL.fromString('omnigraffle://localhost/omnijs-run?script=app.activate()') url.call(function(reply){})
omnigraffle:///omnijs-run?script=url%20%3D%20URL%2EfromString%28%27omnigraffle%3A%2F%2Flocalhost%2Fomnijs-run%3Fscript%3Dapp%2Eactivate%28%29%27%29%0Aurl%2Ecall%28function%28reply%29%7B%7D%29
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