I’d like to use JXA to access the outline numbers that OmniOutliner automatically creates (and best of all, re-creates as I re-order items). I’ve created a small OO-to-Markdown script that works pretty well (I have a few more questions that I’ll save for other posts), but there doesn’t seem to be a property that gives me these numbers.
I’ve tried using:
item.identifier
item.index
item.level – this one seems promising, but only gives a single integer, and not the outline position.
As an example:
Lorem
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem
Lorem ipsum
Lorem ipsum
Lorem ipsum
The bolded text above would be the string “2.2.”.
Is there a simple (undocumented?) property to get that string, or do I need to write my own custom code?
I wonder if the existence of two separate javascript interfaces to OmniOutliner is causing some confusion here ?
Both run in a JSContext – an instance of the Safari JavaScript interpreter, but:
JavaScript for Automation (JXA) interacts with OO through the Apple-supplied Automation object (a JS version of the interface used by AppleScript).
the omniJS JSContext is embedded in OO itself, and interacts with it directly
JXA and omniJS each use quite different sets of objects properties and methods to talk to OmniOutliner.
Your title asks about JXA, which addresses the outline as a nest of:
row objects, which have properties including,
id (but not identifier)
index
level
but the detail of your question looks more likely to be talking not about JXA but about omniJS, which has a dual model of the outline, as a nest of:
TreeNode objects each with paired Item objects, each of which has properties including,
identifier (but not id)
index
level
I think the confusion may have been compounded by the fact that some of the examples posted the other day involved executing/evaluating code in both JSContexts - using JXA for more general automation and interaction with the system, and then getting JXA to launch the omniJS execution of a separate omniJS script source (in the form of a URL) inside OO itself.
In short, its possible that you really are asking about the JXA scripting interface to OmniOutliner, and that JXA answers will be of use to you, but I think you may really need to ask, instead, about the quite different omniJS interface to OmniOutliner.
I’m definitely not yet clear on the distinctions, and didn’t even consider that the object properties could differ between the two interfaces.
I write in TextMate and paste into the omniJS console window to test, but use Keyboard Maestro’s JXA interface to execute the code. I’ve been using the OmniOutliner Automation | API Reference menu item to read about the object properties, but it doesn’t indicate that there are two different sets of properties. Is the [omni-automation.com] oa site more complete?
A good portion of the documentation seems to be a work in progress, so I (admittedly) didn’t dig very deep into the site.
OK, you are definitely talking about omniJS and not JXA :-)
( Neither omni-automation.com nor the omniJS Automation > API Reference pages will talk about the JXA interface to OO (Though I think that your experience suggests that it might be helpful for them to direct JXA interface users elsewhere. The JXA interface to OmniOutliner is documented in the same place as the AppleScript interface (Script Editor > File > Open Dictionary > omnioutiner.app is one route to it )
Probably worth a note to Omni Support to report that this can all be quite confusing, at first, for users, and that prominent (“left to JXA”, “right to omniJS”) signposting and clarification would be helpful.
Having got that far:
while I can see the numbering option in the JXA interface - (heading-prefix attribute of style of row),
and would also expect to also find it among the omniJS style attributes, you might need to ask Omni Support about whether it is yet included in the omniJS interface. I would expect to see in in the Style.Attribute list, (Item.Style then the attributes of a given style), but I haven’t spotted it yet.
Either way, I think the closest that the scripting interfaces will take you is to a combination of the Index (position among siblings), and the numbering component of the Style. You would then need to write your own function to combine those two and derive a prefix string. If it’s literally the position that you want, then you could simply get the index property, and perhaps an ancestral chain of indices if the Item of interest is nested.
(Did you just knock this script out in the 15 minutes between your posts? I’m just digging into javascript, so the syntax is holding me back, but the specifics of JXA and omniJS are bigger mountains. You seem to be quite fluent!)
Once you have chosen a small working subset of JavaScript (see, for example, “JavaScript - the Good Parts” then it becomes quite quick …)
The interface then falls into place too, I think. (I was embarrassed that 15 mins seemed a bit slow - I’ve been using the OmniGraffle interface more than the OO :-)
PS I’ve adjusted the code above so that the root item has index [0], rather than including the virtual root (rootItem) in the ancestral chain.
The only beastly thing is having a library of generic abstractions to paste from – makes things a bit easier and quicker.
If you have Quiver then I can give you a link to a copy of the generic functions that I use, pasting from it like this:
Oh, wow. I’ve never heard of quiver before now. This looks really useful. I’ve been using a combination of gitlab and TextMate to do similar things, but this is intriguing. I’ll at least give the free trial a shot, and would love access to your generics.