New Outline with Graphic Metadata
The workflow example on this page contains two Omni Automation actions that demonstrate how data can be extracted from a document in one application, and used to construct or add to a document in a second application.
The first action extracts the titles of the metadata keys of a selected OmniGraffle graphic, and then uses those key titles to add columns for each key to a newly created OmniOutliner outline document.
The second action populates the new OmniOutliner document with the metadata for all of the selected graphics in the OmniGraffle document.
The initial section of the first action begins with a function for getting the assigned metadata keys for the selected graphic. These keys will be used for creating and titling columns in a new OmniOutliner document.
OmniGraffle: Get Metadata Keys for Selected Graphic | ||
01 | function getKeysForSelectedGraphic(){ | |
02 | var graphics = document.windows[0].selection.graphics | |
03 | if (graphics.length === 1){ | |
04 | data = graphics[0].userData | |
05 | return Object.keys(data) | |
06 | } else { | |
07 | var title = 'SELECTION ERROR' | |
08 | var message = 'Please select a single graphic.' | |
09 | var alert = new Alert(title, message) | |
10 | alert.show() | |
11 | } | |
12 | } | |
13 | var keys = getKeysForSelectedGraphic() |
The second section of the first action contains code for interacting with OmniOutliner. A new document is created and columns are added and titled for each of the extracted metadata keys.
OmniOutliner: New Outline with Columns | ||
01 | function makeNewOutlineWithColumns(colTitles){ | |
02 | Document.makeNewAndShow(doc => { | |
03 | var tree = doc.outline | |
04 | var editor = doc.editors[0] | |
05 | colTitles.forEach(item => { | |
06 | tree.addColumn( | |
07 | Column.Type.Text, | |
08 | editor.afterColumn(tree.columns[tree.columns.length -1]), | |
09 | column => {column.title = item} | |
10 | ) | |
11 | }) | |
12 | }) | |
13 | } |
Here's how the function would be called, passing in an array of column titles:
Calling the Function | ||
01 | var columnTitles = ["Q1", "Q2", "Q3", "Q4"] | |
02 | makeNewOutline(columnTitles) |
Example Plug-In
DOWNLOAD the example document shown in the video.
With the script-to-string preparation completed, we can use the script components to crate an installable Omni Automation action that can be launched from the OmniGraffle Automation menu.
New Outline Document with Columns for Graphic Metadata | ||
01 | /*{ | |
02 | "type": "action", | |
03 | "targets": ["omnigraffle"], | |
04 | "author": "Otto Automator", | |
05 | "identifier": "com.omni-automation.og.outline-with-columns-for-keys", | |
06 | "version": "1.0", | |
07 | "description": "Creates a new OmniOutliner outline document with columns for each metadata tag of the selected graphic.", | |
08 | "label": "Outline with Columns for Keys", | |
09 | "shortLabel": "Outline with Columns", | |
10 | "paletteLabel": "New Outline" | |
11 | }*/ | |
12 | (() => { | |
13 | var action = new PlugIn.Action(function(selection, sender){ | |
14 | // action code | |
15 | ||
16 | // GET METADATA KEYS OF SELECTED GRAPHIC | |
17 | var graphic = selection.graphics[0] | |
18 | var data = graphic.userData | |
19 | var columnTitles = Object.keys(data) | |
20 | console.log(columnTitles) | |
21 | ||
22 | // THE FUNCTION TO BE EXECUTED ON THE TARGET APP | |
23 | function makeNewOutlineWithColumns(titlesArray){ | |
24 | try { | |
25 | Document.makeNewAndShow(doc => { | |
26 | var tree = doc.outline | |
27 | var editor = doc.editors[0] | |
28 | titlesArray.forEach(item => { | |
29 | tree.addColumn( | |
30 | Column.Type.Text, | |
31 | editor.afterColumn(tree.columns[tree.columns.length -1]), | |
32 | column => {column.title = item} | |
33 | ) | |
34 | }) | |
35 | }) | |
36 | } | |
37 | catch(err){ | |
38 | console.error("An error occurred.") | |
39 | throw err | |
40 | } | |
41 | } | |
42 | ||
43 | // CREATE SCRIPT URL WITH FUNCTION | |
44 | var scriptURL = URL.tellFunction( | |
45 | "omnioutliner", | |
46 | makeNewOutlineWithColumns, | |
47 | columnTitles | |
48 | ) | |
49 | ||
50 | // CALL THE SCRIPT URL, PROCESS RESULTS OR ERROR | |
51 | scriptURL.call(callResult => { | |
52 | // PROCESS RESULTS OF SCRIPT | |
53 | if (typeof callResult === "object"){ | |
54 | var callResult = callResult["result"] | |
55 | } | |
56 | console.log(callResult) | |
57 | }, function(err){ | |
58 | // PROCESS SCRIPT ERROR | |
59 | new Alert("SCRIPT ERROR", err.errorMessage).show() | |
60 | console.error(err) | |
61 | }) | |
62 | }); | |
63 | ||
64 | action.validate = function(selection, sender){ | |
65 | // validation code | |
66 | return (selection.graphics.length === 1) | |
67 | }; | |
68 | ||
69 | return action; | |
70 | })(); |
Now that we have a script for generating a new OmniOutliner document with columns matching the metadata to the OmniGraffle graphic, we can create a script for populating the new outline with the metadata from multiple selected OmniGraffle graphics!
Populating Outline with Metadata
The script for populating the newly created OmniOutliner outline document with metadata from the selected OmniGraffle graphics begins with script code for extracting the metadata assigned to each selected graphic.
NOTE: the following scripts assume that all of the selected graphics have the same metadata keys, and that those metadata keys match the columns in the target OmniOutliner outline document.
OmniGraffle: Extract Metadata from Selected Graphics | ||
01 | graphics = document.windows[0].selection.graphics | |
02 | dataArray = [] | |
03 | graphics.forEach(function(graphic){ | |
04 | data = graphic.userData | |
05 | data['Name'] = graphic.name | |
06 | data['Notes'] = graphic.notes | |
07 | dataArray.push(data) | |
08 | }) | |
09 | dataString = JSON.stringify(dataArray) | |
10 | //--> '[{"Iron":"1.4 mg","Calcium":"42 mg","Latin":"Brassica oleracea","Magnesium":"23 mg","Name":"Brussels Sprout","Notes":"The Brussels sprout is a member of the Gemmifera Group of cabbages, grown for its edible buds."},{"Iron":"0.3 mg","Calcium":"12 mg","Latin":"Solanum lycopersicum","Magnesium":"11 mg","Name":"Tomato","Notes":"The tomato is the edible, often red, vegetable, commonly known as a tomato plant. The plant belongs to the nightshade family. The species originated in western South America."}, etc.]' |
The second part of the script populates the outline document by creating a new row for each object, and then putting the keyed metadata in the corresponding row column.
OmniOutliner: Process Passed Metadata | ||
01 | dataArray.forEach(obj => { | |
02 | var item = rootItem.addChild() | |
03 | tags = Object.keys(obj) | |
04 | tags.forEach(tag => { | |
05 | if(tag === "Name"){ | |
06 | item.topic = obj.Name | |
07 | } else if(tag === "Notes"){ | |
08 | item.note = obj.Notes | |
09 | } else { | |
10 | item.setValueForColumn(obj[tag],columns.byTitle(tag)) | |
11 | } | |
12 | }) | |
13 | }) |
Using the same techniques as in the previous action, these script segments can be wrapped in an action template to create and installable action that can be accessed from the OmniGraffle Automation menu.
Populate Metadata Action | ||
01 | /*{ | |
02 | "type": "action", | |
03 | "targets": ["omnigraffle"], | |
04 | "author": "Otto Automator", | |
05 | "identifier": "com.omni-automation.og.populate-outline-with-metadata", | |
06 | "version": "1.0", | |
07 | "description": "Creates a new OmniOutliner outline document with columns for each metadata tag of the selected graphic.", | |
08 | "label": "Populate Outline with Metadata", | |
09 | "shortLabel": "Metadata to Outline", | |
10 | "paletteLabel": "Populate Outline" | |
11 | }*/ | |
12 | (() => { | |
13 | var action = new PlugIn.Action(function(selection, sender){ | |
14 | // action code | |
15 | ||
16 | // ADD TO METADATA OBJECTS OF SELECTED GRAPHICS | |
17 | var objectArray = [] | |
18 | selection.graphics.forEach(graphic => { | |
19 | var data = graphic.userData | |
20 | data['Name'] = graphic.name | |
21 | data['Notes'] = graphic.notes | |
22 | objectArray.push(data) | |
23 | }) | |
24 | ||
25 | // THE FUNCTION TO BE EXECUTED ON THE TARGET APP | |
26 | function populateOutline(dataArray){ | |
27 | try { | |
28 | dataArray.forEach(obj => { | |
29 | var item = rootItem.addChild() | |
30 | tags = Object.keys(obj) | |
31 | tags.forEach(tag => { | |
32 | if(tag === "Name"){ | |
33 | item.topic = obj.Name | |
34 | } else if(tag === "Notes"){ | |
35 | item.note = obj.Notes | |
36 | } else { | |
37 | item.setValueForColumn(obj[tag],columns.byTitle(tag)) | |
38 | } | |
39 | }) | |
40 | }) | |
41 | return true | |
42 | } | |
43 | catch(error){ | |
44 | console.error("An error occurred.") | |
45 | throw error | |
46 | } | |
47 | } | |
48 | ||
49 | // CREATE SCRIPT URL WITH FUNCTION | |
50 | var scriptURL = URL.tellFunction( | |
51 | "omnioutliner", | |
52 | populateOutline, | |
53 | objectArray | |
54 | ) | |
55 | ||
56 | // CALL THE SCRIPT URL, PROCESS RESULTS OR ERROR | |
57 | scriptURL.call(callResult => { | |
58 | // PROCESS RESULTS OF SCRIPT | |
59 | if (typeof callResult === "object"){ | |
60 | var callResult = callResult["result"] | |
61 | } | |
62 | console.log(callResult) | |
63 | if(callResult === true){URL.fromString("omnioutliner:///open?").open()} | |
64 | }, function(err){ | |
65 | // PROCESS SCRIPT ERROR | |
66 | new Alert("SCRIPT ERROR", err.errorMessage).show() | |
67 | console.error(err) | |
68 | }) | |
69 | }); | |
70 | ||
71 | action.validate = function(selection, sender){ | |
72 | // validation code | |
73 | return (selection.graphics.length > 0) | |
74 | }; | |
75 | ||
76 | return action; | |
77 | })(); |
This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.