Search or Find only in one level?

Is there a way to search for a search string in only the top level of an outline?

I have a very long outline and would like to have a search find certain words in the titles (or top levels) and not in all the text that is indented under the titles.

Using JavaScript for Automation you might start with something like this:

var a = Application.currentApplication(),
    sa = (a.includeStandardAdditions = true, a);

(function (dctOptions) {
    'use strict';

    var oo = Application("com.omnigroup.OmniOutliner4"),
        ds = oo.documents;

    if (ds.length) {

        var lstRows = ds[0].rows.where({
            _and: [
                {
                    level: dctOptions.level
                },{
                    topic: {
                        _contains: dctOptions.text
                    }
                }
            ]
        });

        if (lstRows.length > 0) {
            oo.activate();
            oo.select(lstRows)
        }
    }
})({
    level: 1,
    text: (
        sa.activate,
        sa.displayDialog('Search for:', {
            defaultAnswer: '',
            buttons: ['Cancel', 'OK'],
            defaultButton: 'OK',
            cancelButton: 'Cancel',
            withTitle: 'Search at one level only',
            withIcon: sa.pathToResource('OmniOutliner.icns', {
                inBundle: 'Applications/OmniOutliner.app'
            }),
            givingUpAfter: 30
        }).textReturned
    )
});
1 Like

Thank you for that … alas, I have no idea what to do with this.

How do I invoke it?

You can test it by pasting it into Script Editor, and selecting JavaScript from the language selector at top left, before choosing Run.

If you want to add it to the OmniOutliner Script Menu, you can make sure that Show Script menu in menu bar is checked in Script Editor preferences, and then save the script as an .scpt file, and while OmniOutliner has focus, use that menu to place the .scpt file in the OmniOutliner Scripts Folder

That worked. Thank you.

How would I edit the script to have it search level 2 or level 3? Or 1,2 and 3?

The trick is to adjust the .where() or .whose() condition which is used to select matching rows.

For example, to search in rows level 1-3, we could write:

level: {
  '<=': dctOptions.maxLevel
}

and set the .maxLevel option to 3, as in the code below.

For the full range of filter options, see:

https://developer.apple.com/library/mac/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/OSX10-10.html

Edit for search levels 1-3 (you can adjust the value of intMaxLevel in the first row)

var intMaxLevel = 3,
    a = Application.currentApplication(),
    sa = (a.includeStandardAdditions = true, a);

(function (dctOptions) {
    'use strict';

    var oo = Application("com.omnigroup.OmniOutliner4"),
        ds = oo.documents;

    if (ds.length) {

        var lstRows = ds[0].rows.where({
            _and: [{
                level: {
                    '<=': dctOptions.maxLevel
                }
            }, {
                topic: {
                    _contains: dctOptions.text
                }
            }]
        });

        if (lstRows.length > 0) {
            oo.activate();
            oo.select(lstRows)
        }
    }
})({
    maxLevel: intMaxLevel,
    text: (
        sa.activate,
        sa.displayDialog('Search Levels 1-' + intMaxLevel + ' for:', {
            defaultAnswer: '',
            buttons: ['Cancel', 'OK'],
            defaultButton: 'OK',
            cancelButton: 'Cancel',
            withTitle: 'Search at one level only',
            withIcon: sa.pathToResource('OmniOutliner.icns', {
                inBundle: 'Applications/OmniOutliner.app'
            }),
            givingUpAfter: 30
        }).textReturned
    )
});

I would certainly like this functionality built into OmniOutliner. JavaScript is over my head. I have the same basic problem of a large outline and I do not want to get hits on lower level text (of which there is a lot)