Graphics Metadata

One of the great power-user features of OmniGraffle is the ability to assign metadata to objects. Assigned metadata can then be retrieved and used in automating the construction and formatting of documents. Just watch the video at the bottom of this page to see this technique in action. Very powerful indeed!

This webpage describes the various metadata properties and methods that are available for your use in creating automated publishing tools.

Metadata Properties and User-Data Keys

OmniGraffle includes a robust architecture for associating graphic objects with metadata that includes object properties and user-defined pairs of data keys and values called user-data keys. (below: metadata settings for macOS (left), and iOS (right))

metadata-macos-ios

Every graphic has four basic metadata properties: id, name, notes, and userData. The id and name  1  properties can be used to identify a graphic, and the notes  2  property can store a description or other text related to the graphic.

User-Data Keys are one or more user-defined pairs of key names and data values that are assigned to a graphic object. A key  3  could be any type of identifier, such as a SKU or product number, or a person’s name. The key value  4  can be any type of data expressed as a string.

Graphic Metadata Methods

Here are Graphic instance methods for getting and setting user data keys and values:

function getKeyValueForSelectedGraphic(keyName){ var graphics = document.windows[0].selection.graphics if (graphics.length == 1){ data = graphics[0].userData[keyName] if (data == null){ alert = new Alert('KEY ERROR','The key “' + keyName + '” is not assigned to the selected graphic.') alert.show(function(result){}) } else { return data } } else { alert = new Alert('SELECTION ERROR','Please select a single graphic.') alert.show(function(result){}) } }
function setKeyAndValueForSelectedGraphic(keyName,keyValue){ var graphics = document.windows[0].selection.graphics if (graphics.length == 1){ graphics[0].setUserData(keyName,keyValue) } else { alert = new Alert('SELECTION ERROR','Please select a single graphic.') alert.show(function(result){}) } }
 

Canvas Metadata Methods

The power of metadata is in both its usefulness as an identifier and as a container for information. Tagged-Container Publishing is a technique widely used in industries that create large amounts of content. Countless catalogs, publications, and websites that feature repeating elements rely on tagging elements with metadata to benefit from the power of automation.

After the graphics have been tagged, the next step in the automation process is to iterate a list of the identifiers and locate their associated containers in the document. The following functions are used for locating tagged graphics and for retrieving their tagged data:

As an example of how these functions can be used, here’s a function that locates a graphic based upon a specified user-data key and value, and then extracts the found graphic’s notes:

function getNotesOfGraphicWithUserDataForKey(keyValue,keyName){ cnvs = document.windows[0].selection.canvas graphic = cnvs.graphicWithUserDataForKey(keyValue, keyName) if(graphic == null){ errMsg = 'The key/value pair “' + keyName + '/' + keyValue + '” is not assigned to a graphic on the current canvas.' alert = new Alert('USER DATA ERROR',errMsg) alert.show(function(result){}) } else { return [graphic,graphic.notes] } }
[aGraphic, aGraphicNotes] = getNotesOfGraphicWithUserDataForKey('323698','SKU')

The result of the function is an array containing an object reference to the located graphic, and its notes. You can call the function like this:

Tag and Import into Containers using Web-Data

Here is an example of tagged-container publishing with OmniGraffle in action. Using OmniJS scripts embedded in a webpage, graphics in an OmniGraffle document are tagged with metadata, and then those tags are used to import images into the tagged containers based upon URLs placed in their metadata, and to create adjacent text boxes containing the notes from the graphics.

Try it Yourself!

DOWNLOAD the example OmniGraffle file, and visit the webpage shown in the video.

Functions from Example

Here are two of the OmniJS functions used in the example. The functions are embedded in the example webpage, and are triggered when their corresponding buttons are pressed.

The following script extracts the notes from the selected graphics, and creates a new text shape containing the notes placed at the user-indicated position:

// default settings var defaultOffset = 12 var defaultTextSize = 14 // prompt for placement location var alert = new Alert("Notes Placement", "Should the notes be placed to the left, right, or below the selected graphic?") alert.addOption("Right") alert.addOption("Left") alert.addOption("Below") alert.show(function(result){ var cnvs = document.windows[0].selection.canvas var slds = document.windows[0].selection.solids if (result == 0){ slds.forEach(function(sld){ sName = sld.name sNotes = sld.notes cRect = sld.geometry nRect = new Rect(cRect.maxX + defaultOffset, cRect.minY, cRect.width, cRect.height) aShape = cnvs.addShape('Rectangle',nRect) aShape.text = sNotes aShape.name = sName aShape.shadowColor = null aShape.strokeType = null aShape.fillType = null aShape.autosizing = TextAutosizing.Overflow aShape.textHorizontalAlignment = HorizontalTextAlignment.Left aShape.textHorizontalPadding = 0 aShape.textVerticalPlacement = VerticalTextPlacement.Top aShape.textVerticalPadding = 0 aShape.textSize = defaultTextSize }) } else if (result == 1){ slds.forEach(function(sld){ sName = sld.name sNotes = sld.notes cRect = sld.geometry nRect = new Rect(cRect.minX - defaultOffset - cRect.width, cRect.minY, cRect.width, cRect.height) aShape = cnvs.addShape('Rectangle',nRect) aShape.text = sNotes aShape.name = sName aShape.shadowColor = null aShape.strokeType = null aShape.fillType = null aShape.autosizing = TextAutosizing.Overflow aShape.textHorizontalAlignment = HorizontalTextAlignment.Left aShape.textHorizontalPadding = 0 aShape.textVerticalPlacement = VerticalTextPlacement.Top aShape.textVerticalPadding = 0 aShape.textSize = defaultTextSize }) } else { slds.forEach(function(sld){ sName = sld.name sNotes = sld.notes cRect = sld.geometry nRect = new Rect(cRect.minX, cRect.maxY + defaultOffset, cRect.width, cRect.height) aShape = cnvs.addShape('Rectangle',nRect) aShape.text = sNotes aShape.name = sName aShape.shadowColor = null aShape.strokeType = null aShape.fillType = null aShape.autosizing = TextAutosizing.Overflow aShape.textHorizontalAlignment = HorizontalTextAlignment.Left aShape.textHorizontalPadding = 0 aShape.textVerticalPlacement = VerticalTextPlacement.Top aShape.textVerticalPadding = 0 aShape.textSize = defaultTextSize }) } })
omnigraffle:///omnijs-run?script=%2F%2F%20default%20settings%0Avar%20defaultOffset%20%3D%2012%0Avar%20defaultTextSize%20%3D%2014%0A%0A%2F%2F%20prompt%20for%20placement%20location%0Avar%20alert%20%3D%20new%20Alert%28%22Notes%20Placement%22%2C%20%22Should%20the%20notes%20be%20placed%20to%20the%20left%2C%20right%2C%20or%20below%20the%20selected%20graphic%3F%22%29%0Aalert%2EaddOption%28%22Right%22%29%0Aalert%2EaddOption%28%22Left%22%29%0Aalert%2EaddOption%28%22Below%22%29%0Aalert%2Eshow%28function%28result%29%7B%0A%09var%20cnvs%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Ecanvas%0A%09var%20slds%20%3D%20document%2Ewindows%5B0%5D%2Eselection%2Esolids%0A%09if%20%28result%20%3D%3D%200%29%7B%0A%09%09slds%2EforEach%28function%28sld%29%7B%0A%09%09%09sName%20%3D%20sld%2Ename%0A%09%09%09sNotes%20%3D%20sld%2Enotes%0A%09%09%09cRect%20%3D%20sld%2Egeometry%0A%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EmaxX%20%2B%20defaultOffset%2C%20cRect%2EminY%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09aShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09aShape%2Etext%20%3D%20sNotes%0A%09%09%09aShape%2Ename%20%3D%20sName%0A%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09aShape%2EfillType%20%3D%20null%0A%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09aShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09aShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09aShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09aShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%7D%29%0A%09%7D%20else%20if%20%28result%20%3D%3D%201%29%7B%0A%09%09slds%2EforEach%28function%28sld%29%7B%0A%09%09%09sName%20%3D%20sld%2Ename%0A%09%09%09sNotes%20%3D%20sld%2Enotes%0A%09%09%09cRect%20%3D%20sld%2Egeometry%0A%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EminX%20-%20defaultOffset%20-%20cRect%2Ewidth%2C%20cRect%2EminY%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09aShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09aShape%2Etext%20%3D%20sNotes%0A%09%09%09aShape%2Ename%20%3D%20sName%0A%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09aShape%2EfillType%20%3D%20null%0A%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09aShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09aShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09aShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09aShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%7D%29%0A%09%7D%20else%20%7B%0A%09%09slds%2EforEach%28function%28sld%29%7B%0A%09%09%09sName%20%3D%20sld%2Ename%0A%09%09%09sNotes%20%3D%20sld%2Enotes%0A%09%09%09cRect%20%3D%20sld%2Egeometry%0A%09%09%09nRect%20%3D%20new%20Rect%28cRect%2EminX%2C%20cRect%2EmaxY%20%2B%20defaultOffset%2C%20cRect%2Ewidth%2C%20cRect%2Eheight%29%0A%09%09%09aShape%20%3D%20cnvs%2EaddShape%28%27Rectangle%27%2CnRect%29%0A%09%09%09aShape%2Etext%20%3D%20sNotes%0A%09%09%09aShape%2Ename%20%3D%20sName%0A%09%09%09aShape%2EshadowColor%20%3D%20null%0A%09%09%09aShape%2EstrokeType%20%3D%20null%0A%09%09%09aShape%2EfillType%20%3D%20null%0A%09%09%09aShape%2Eautosizing%20%3D%20TextAutosizing%2EOverflow%0A%09%09%09aShape%2EtextHorizontalAlignment%20%3D%20HorizontalTextAlignment%2ELeft%0A%09%09%09aShape%2EtextHorizontalPadding%20%3D%200%0A%09%09%09aShape%2EtextVerticalPlacement%20%3D%20VerticalTextPlacement%2ETop%0A%09%09%09aShape%2EtextVerticalPadding%20%3D%200%0A%09%09%09aShape%2EtextSize%20%3D%20defaultTextSize%0A%09%09%7D%29%0A%09%7D%0A%7D%29

The following script scans all graphics on the current canvas for those having a specific user-data tag (“SKU”), and then extract the value of the graphic’s user-data tag (“URL”), and use its value to download and import the image referenced by the URL, into the graphic.

var cnvs = document.windows[0].selection.canvas var dataKey = 'SKU' var urlKey = 'URL' var keyValues = new Array() var urlValues = new Array() for(i = 0; i < cnvs.graphics.length; i++){ aGraph = cnvs.graphics[i] aValue = aGraph.userData[dataKey] if(aValue != null){ keyValues.push(aValue) u = aGraph.userData[urlKey] if(u != null){ urlValues.push(u) } else { urlValues.push('') } } } var valCount = keyValues.length for (i = 0; i < valCount; i++) { var keyValue = keyValues[i] aStr = urlValues[i] fileURL = URL.fromString(aStr) fileURL.fetch((function(keyValue, data) { aGraph = cnvs.graphicWithUserDataForKey(keyValue, dataKey) aGraph.image = addImage(data) }).bind(this, keyValue)) }

Other Examples

Here are two more examples of how a graphic’s metadata can be used to alter the parent graphic.

In the first example, the contents of the metadata pair “Fill Color” is a text string representing an array of RGB color values: "[1,0,0,1]"

The script retrieves this string from the metadata of the selected graphics, converts it into numeric values, and sets the fill color to he generated Color value:

metaTag = 'Fill Color' shapes = document.windows[0].selection.solids shapes.forEach(function(shape){ tagValue = shape.userData[metaTag] colorValue = JSON.parse(tagValue) newColor = Color.RGB(colorValue[0], colorValue[1], colorValue[2], 1) shape.fillColor = newColor })

The second example script checks the value of a specific metadata pair and based upon the value (which is converted from a string into an integer), performs an action, like setting fill color:

metaTag = 'Fill Color' shapes = document.windows[0].selection.solids shapes.forEach(function(shape){ tagValue = parseInt(shape.userData[metaTag]) if (tagValue === 1){ newFillColor = Color.red } else if (tagValue === 2){ newFillColor = Color.green } else { newFillColor = Color.blue } shape.fillColor = newFillColor })
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