How to Get the Enum Name or Value from OmniGraffle JavaScript Objects
When automating macOS or iOS applications like OmniGraffle using JavaScript (OmniJS), developers frequently encounter enumeration objects. If you have ever logged an object like graphic.textHorizontalAlignment and seen [object HorizontalTextAlignment: Left], your immediate reaction is probably: “Great, how do I actually get the string 'Left' out of this object?”
Trying traditional property lookups like graphic.textHorizontalAlignment.Left or Object.values() usually results in undefined. In this guide, we'll explain why this happens and explore the best ways to extract the enum key or string representation cleanly.
Why Does This Happen?
In OmniGraffle's JavaScript runtime (built on JavaScriptCore and native bridging), enums are modeled similarly to Swift or Objective-C enums rather than plain JavaScript objects:
HorizontalTextAlignmentis the enum container (holding static reference objects such asCenter,Left, andRight).graphic.textHorizontalAlignmentreturns one specific instance/value of that enum, not the parent namespace.
Because the instance is a native reference pointer rather than a standard dictionary, attempts to access properties directly on the instance return undefined.
Solution 1: Check for the .name Property
In modern Omni Automation (OmniJS), many native enumeration instances expose an internal .name property. If you haven't tried this specific property yet, test it on your instance:
const alignment = graphic.textHorizontalAlignment;
console.log(alignment.name); // Often yields: "Left"
If this returns undefined in your specific OmniGraffle build, proceed to the reverse-lookup or string extraction methods below.
Solution 2: Reverse Lookup via HorizontalTextAlignment.all
Most OmniJS enums implement an .all array containing all possible enum values. You can write a helper function to find which static definition matches the graphic's property:
function getEnumKey(enumContainer, targetValue) {
// If the enum provides an 'all' list
if (Array.isArray(enumContainer.all)) {
const match = enumContainer.all.find(item => item === targetValue);
if (match && match.name) return match.name;
}
// Fallback: Check static properties on the container
for (const key of Object.getOwnPropertyNames(enumContainer)) {
try {
if (enumContainer[key] === targetValue) {
return key;
}
} catch (e) {
// Ignore inaccessible internal getters
}
}
return null;
}
// Usage:
const alignmentName = getEnumKey(HorizontalTextAlignment, graphic.textHorizontalAlignment);
console.log(alignmentName); // Output: "Left"
Solution 3: Parsing the Template Literal String (Quick & Reliable)
Notice in your logs that template literal interpolation yields the descriptive representation:
console.log(`${graphic.textHorizontalAlignment}`);
// Output: [object HorizontalTextAlignment: Left]
Omni Automation hooks into custom string formatting for interpolation and debugging. If you simply need the string name and want to avoid scanning the enum properties every time, you can extract the label using a regular expression:
function getAlignmentName(alignmentObj) {
const str = `${alignmentObj}`;
const match = str.match(/:
?\s*([A-Za-z0-9_]+)\]$/);
return match ? match[1] : null;
}
const name = getAlignmentName(graphic.textHorizontalAlignment);
console.log(name); // Output: "Left"
Solution 4: Avoid String Comparisons (The Idiomatic Way)
If you need the name only to execute conditional business logic, consider sticking to direct identity comparisons. This avoids fragile string parsing and aligns with native OmniJS design patterns:
switch (graphic.textHorizontalAlignment) {
case HorizontalTextAlignment.Left:
// Handle Left alignment
break;
case HorizontalTextAlignment.Center:
// Handle Center alignment
break;
case HorizontalTextAlignment.Right:
// Handle Right alignment
break;
}
Alternatively, map the enum objects to your own dictionary if you need custom strings or mappings:
const ALIGNMENT_LABELS = new Map([
[HorizontalTextAlignment.Left, 'Left'],
[HorizontalTextAlignment.Center, 'Center'],
[HorizontalTextAlignment.Right, 'Right'],
[HorizontalTextAlignment.Justify, 'Justify']
]);
const label = ALIGNMENT_LABELS.get(graphic.textHorizontalAlignment);
console.log(label); // "Left"
Summary
- Do not query variants on the instance (e.g.,
graphic.textHorizontalAlignment.Leftis invalid). - Test
graphic.textHorizontalAlignment.namefirst. - If you require the exact string representation dynamically without hardcoded conditions, use regex against the template-interpolated string
`${graphic.textHorizontalAlignment}`. - For control flow, prefer direct reference equality (
=== HorizontalTextAlignment.Left) or aMaplookup.