Finding Outline Items
It is common for scripts to perform their automation tasks by first locating a set of objects that meet a specified set of criteria, and then process the found items. This page contains examples and techniques of how to locate items in an outline document.
The apply(…) instance method of the Item class is very useful for locating items whose properties match specified criteria. The following example functions use this method to locate specific items.
The Item.ApplyResult Class
By default, the apply() method when used with the rootItem object, will iterate every item of the outline, processing each item with the processing code you provide. Optionally, you can use the properties of the Item.ApplyResult class to indicate if an iterated item should be ignored, or if the iteration process should stop.
Skip (Item.ApplyResult r/o) • The descendants of the current Item are skipped.
Stop (Item.ApplyResult r/o) • The call to Item.apply terminates with no further items being processed.
all (Array r/o) • An array of all items of this enumeration. This property is often used when creating action forms.
Using the apply() function to process every item in the outline document:
The apply() Function | ||
01 | rootItem.apply(function(item){ | |
02 | // process each item | |
03 | }) |
Using the apply() function to locate and process a specific item:
The apply() Function: Stop on Match | ||
01 | var thisIsTheOne = null | |
02 | rootItem.apply(function(item){ | |
03 | // stop the iteration process when a match is found | |
04 | if (item.topic.startsWith(stringToMatch)){ | |
05 | thisIsTheOne = item | |
06 | return Item.ApplyResult.Stop | |
07 | } | |
08 | }) | |
09 | if (thisIsTheOne){//process the matched item} |
Using the apply() function to process all items except those whose top-level ancestor matches specific requirements:
The apply() Function: Skip on Match | ||
01 | rootItem.apply(function(item){ | |
02 | // do not process if condition met | |
03 | if (item.topic.startsWith(stringToMatch)){ | |
04 | return Item.ApplyResult.Skip | |
05 | } else { | |
06 | // process the item | |
07 | } | |
08 | }) |
Finding by Identifier
For example, here is a function that returns an object reference to the outline item whose identifier matches the one passed into the function. The result will be null if no matching item is located.
Locate Item by ID | ||
01 | function itemWithID(itemID){ | |
02 | var matchedItem = null | |
03 | rootItem.apply(function(item){ | |
04 | if (item.identifier == itemID){ | |
05 | matchedItem = item | |
06 | console.log(matchedItem.topic) | |
07 | return Item.ApplyResult.Stop | |
08 | } | |
09 | }) | |
10 | return matchedItem | |
11 | } |
NOTE: although the previous example is a valid use of the apply() method, for this example, locating an item by ID is better accomplished using the the itemWithIdentifier() method of the Outline class:
Locate Item with ID | ||
01 | item = document.outline.itemWithIdentifier(itemID) |
The following function uses the itemWithIdentifier() method of the Outline class to select the item whose ID matches the provided ID string. Note that the reveal(…) function is called before using the select(…) function to ensure that the targeted item is visible before selecting it.
Select Item with ID | ||
01 | function selectItemWithID(itemID){ | |
02 | item = document.outline.itemWithIdentifier(itemID) | |
03 | if (item != null){ | |
04 | editor = document.editors[0] | |
05 | node = editor.nodeForItem(item) | |
06 | editor.reveal([node]) | |
07 | editor.select([node]) | |
08 | } | |
09 | } |
Finding Items by Topic Contents
Locating items based upon their topics (text contents) is a common technique.
Here’s a function, incorporating the apply() method, that returns an object reference to the first item whose text matches the provided string:
First Item Whose Topic Matches String | ||
01 | function firstItemWhoseTopicMatchesString(str){ | |
02 | var matchedItem = null | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic == str){ | |
05 | matchedItem = item | |
06 | return Item.ApplyResult.Stop | |
07 | } | |
08 | }) | |
09 | return matchedItem | |
10 | } |
A version of the function that returns an array of object references to all items whose topic matches the provided string:
Every Item Whose Topic Matches String | ||
01 | function everyItemWhoseTopicMatchesString(str){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic == str){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
Another search example that returns an object reference to the first item whose text begins with the indicated text:
First Item Whose Topic Begins With String | ||
01 | function firstItemWhoseTopicBeginsWithString(str){ | |
02 | var matchedItem = null | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.startsWith(str)){ | |
05 | matchedItem = item | |
06 | return Item.ApplyResult.Stop | |
07 | } | |
08 | }) | |
09 | return matchedItem | |
10 | } |
A function for returning an array of object references to every item whose topic begins with the provided string:
Every Item Whose Topic Begins With String | ||
01 | function everyItemWhoseTopicBeginsWithString(str){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.startsWith(str)){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
Another search example that returns an object reference to the first item whose text ends with the indicated text:
First Item Whose Topic Ends With String | ||
01 | function firstItemWhoseTopicEndsWithString(str){ | |
02 | var matchedItem = null | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.endsWith(str)){ | |
05 | matchedItem = item | |
06 | return Item.ApplyResult.Stop | |
07 | } | |
08 | }) | |
09 | return matchedItem | |
10 | } |
A function for returning an array of object references to every item whose topic ends with the provided string:
Every Item Whose Topic Ends With String | ||
01 | function everyItemWhoseTopicEndsWithString(str){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.endsWith(str)){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
A search example that returns an object reference to the first item whose text includes the indicated text. Notes the includes() method is case sensitive.
First Item Whose Topic Includes String | ||
01 | function firstItemWhoseTopicIncludesString(str){ | |
02 | var matchedItem = null | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.includes(str)){ | |
05 | matchedItem = item | |
06 | return Item.ApplyResult.Stop | |
07 | } | |
08 | }) | |
09 | return matchedItem | |
10 | } |
A function for returning an array of object references to every item whose topic includes the provided string:
Every Item Whose Topic Includes String | ||
01 | function everyItemWhoseTopicIncludesString(str){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.topic.includes(str)){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
Finding Items by State
Another common search is based upon the state of the item, or the status of it’s checkbox column. This is accomplished by scanning the nodes of the Editor’s rootNode object, since the visible state of items may not match the settings shown in the document window.
The result of the following routine is an array of outline items (rows) whose state matches the value provided as input to the handler.
Find by State | ||
01 | function everyItemWhoseStateMatchesValue(stateValue){ | |
02 | var matchedItems = new Array() | |
03 | mainNode = document.editors[0].rootNode | |
04 | mainNode.apply(function(node){ | |
05 | nodeState = node.valueForColumn(document.outline.statusColumn) | |
06 | if (node != mainNode && nodeState == stateValue){ | |
07 | matchedItems.push(node.object) | |
08 | } | |
09 | }) | |
10 | return matchedItems | |
11 | } |
And here is how the previous function could be called:
Finding Items by State | ||
01 | checkedItems = everyItemWhoseStateMatchesValue(State.Checked) | |
02 | uncheckedItems = everyItemWhoseStateMatchesValue(State.Unchecked) | |
03 | mixedStatusItems = everyItemWhoseStateMatchesValue(State.Mixed) |
And here's a variation of the previous function for identifying items by state, that use the JavaScript filter() method:
Filter All Items by State | ||
01 | function itemsByState(stateValue){ | |
02 | var editor = document.editors[0], | |
03 | status = document.outline.statusColumn; | |
04 | ||
05 | return rootItem.descendants.filter(function(row){ | |
06 | return editor.nodeForItem(row).valueForColumn(status) === stateValue; | |
07 | }) | |
08 | } | |
09 | itemsByState(State.Mixed) |
Finding Items by Column Cell Value
Here’s an example script that will apply a named style to the row whose cell of a specified column has a value meeting certain requirements, in this case whose numeric value is greater than 100. Note that depending on the applied column format the cell’s value may be Text or Decimal:
Style Row whose Cell Value is Greater Than 100 | ||
01 | var nStyles = document.outline.namedStyles | |
02 | var nStyle = nStyles.byName('Highlight 3') | |
03 | var targetColumn = columns.byTitle('STATS') | |
04 | var targetValue = 100 | |
05 | rootItem.apply(function(item){ | |
06 | var value = item.valueForColumn(targetColumn) | |
07 | if (value && value instanceof Text){ | |
08 | if (Number(textObj.string) > targetValue){ | |
09 | item.style.setStyle(nStyle) | |
10 | } | |
11 | } else if (value && value instanceof Decimal){ | |
12 | var compVal = Decimal.fromString(targetValue.toString()) | |
13 | if (value.compare(compVal) > 0){ | |
14 | item.style.setStyle(nStyle) | |
15 | } | |
16 | } | |
17 | }) |
Finding Items by Notes
Nulla vitae elit libero, a pharetra augue. Vestibulum id ligula porta felis euismod semper. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Maecenas sed diam eget risus varius blandit sit amet non magna. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Aenean lacinia bibendum nulla sed consectetur. Donec ullamcorper nulla non metus auctor fringilla.
Every Item Whose Note Includes String | ||
01 | function everyItemWhoseNoteIncludesString(str){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.note.includes(str)){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
Every Item Whose Note is Empty | ||
01 | function everyItemWhoseNoteIsEmpty(){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.note == ''){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
Every Item Whose Note is Not Empty | ||
01 | function everyItemWhoseNoteIsNotEmpty(){ | |
02 | var matchedItems = new Array() | |
03 | rootItem.apply(function(item){ | |
04 | if (item.note != ''){ | |
05 | matchedItems.push(item) | |
06 | } | |
07 | }) | |
08 | return matchedItems | |
09 | } |
This webpage is in the process of being developed. Any content may change and may not be accurate or complete at this time.