“Actions” or “Tasks”

When interacting with the OmniFocus application’s user-interface (UI for short), you will encounter the term “Action” which refers to a new to-do item for a project. However, in the OmniPlan application, such a time-related element is called a “Task.”

The Omni Automation support in OmniFocus considers the terms “action” and “task” to be functionally synonymous, and refers to the scriptable element representing an “action” as a “task.”

In other words: a “task” is a something that needs doing, and “action” is the element in the OmniFocus interface that represents that need or to-do item. Scripts reference tasks, and the graphical user-interface of OmniFocus references actions. In the following documentation, consider tasks to be equivalent to actions.

Properties

An instance of the Task class is defined by the value of its properties.

Task.Status

The values for the taskStatus property of the Task class:

task = inbox[0] if(task){taskStatusObj = task.taskStatus}

Creating Tasks

To create an instance of the Task class, the standard JavaScript new item constructor is used:

task = new Task("My Task")
omnifocus://localhost/omnijs-run?script=try%7Btask%20%3D%20new%20Task%28%22My%20Task%22%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D
task = new Task("My Task", inbox.beginning)
omnifocus://localhost/omnijs-run?script=try%7Btask%20%3D%20new%20Task%28%22My%20Task%22%2C%20inbox%2Ebeginning%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Once a task instance has been created, the value of its properties can be set:

task = new Task("My Task", inbox.beginning) task.note = "This is the note for the created task." task.flagged = true
omnifocus://localhost/omnijs-run?script=try%7Btask%20%3D%20new%20Task%28%22My%20Task%22%2C%20inbox%2Ebeginning%29%0Atask%2Enote%20%3D%20%22This%20is%20the%20note%20for%20the%20created%20task%2E%22%0Atask%2Eflagged%20%3D%20true%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Here's an example script that creates and then displays a task in the application interface:

task = new Task("My New Task", inbox.beginning) urlString = "omnifocus:///task/" + task.id.primaryKey URL.fromString(urlString).call(()=>{})
omnifocus://localhost/omnijs-run?script=try%7Btask%20%3D%20new%20Task%28%22My%20New%20Task%22%2C%20inbox%2Ebeginning%29%0AurlString%20%3D%20%22omnifocus%3A%2F%2F%2Ftask%2F%22%20%2B%20task%2Eid%2EprimaryKey%0AURL%2EfromString%28urlString%29%2Ecall%28%28%29%3D%3E%7B%7D%29%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

 1  The JavaScript new item constructor takes the name for the new task as input, and optionally the insertion postion in the task’s parent container, as a second input parameter. The result is an object reference to the newly created task, which is stored in the variable: task

 2  Every element of the OmniFocus database, including tasks, projects, and folders, shares the id and primaryKey properties, which generate a unique identifier string for each element. This identifer can be appended to an OmniFocus URL that will cause the identified item to display in the app UI when the URL is called.

 3  The URL string is converted into a URL object using the fromString(…) method of the URL class, which is then called using the call(…) method of the same class.

Task Instance Functions

Here are the functions that can be performed with an instance of the Task class:

Using Task Functions

The following script examples demonstrate how to use some of the functions of the Task class:

This first script demonstrates how to retrieve references to the currently selected tasks. The result will be an array of object references, or an empty array if no tasks are selected.

document.windows[0].selection.tasks

The next script uses the apply(…) function to generate an array of object references to all of the tasks within the entire inbox heirarchy:

var masterTaskArray = new Array() inbox.apply(task => masterTaskArray.push(task)) console.log(masterTaskArray)

The next script uses the apply(…) function to generate an array of object references to all of the tasks contained within the entire hierarchy of folders and projects:

var masterTaskArray = new Array() library.apply(function(item){ if (item instanceof Project && item.task.hasChildren){ masterTaskArray.push(item.task.children) } }) console.log(masterTaskArray)

The next script uses the apply(…) function to generate an array of object references to all of the tasks contained within the entire hierarchy of folders and projects and the inbox, in other words, all tasks in the database:

var masterTaskArray = new Array() library.apply(function(item){ if (item instanceof Project && item.task.hasChildren){ masterTaskArray.push(item.task.children) } }) inbox.apply(task => masterTaskArray.push(task)) console.log(masterTaskArray)

You can combine the use of the apply(…) function with comparison operator to locate tasks whose status is due soon. Note the use of the hasChildren and children properties of the Task class to recognize if a task is acuatlly a task group. The resutling array will contain references to all project tasks that are due soon.

var matchingTasks = new Array() library.apply(function(item){ if (item instanceof Project && item.task.hasChildren){ item.task.children.forEach(tsk => { if (tsk.taskStatus === Task.Status.DueSoon){ matchingTasks.push(tsk) } }) } })

Using the previous ability to locate project tasks that are due soon, we can the generate an array of references to the projects containing those actions, and they use the resulting array of object references as the value for the focus property of the Window class to focus the projects in the OmniFocus wndow.

var parentProjects = new Array() library.apply(function(item){ if (item instanceof Project && item.task.hasChildren){ item.task.children.forEach(tsk => { if (tsk.taskStatus === Task.Status.DueSoon){ parentProjects.push(tsk.containingProject) } }) } }) if (parentProjects.length > 0){ document.windows[0].perspective = Perspective.BuiltIn.Projects document.windows[0].focus = parentProjects }
omnifocus://localhost/omnijs-run?script=try%7Bvar%20parentProjects%20%3D%20new%20Array%28%29%0Alibrary%2Eapply%28function%28item%29%7B%0A%09if%20%28item%20instanceof%20Project%20%26%26%20item%2Etask%2EhasChildren%29%7B%0A%09%09item%2Etask%2Echildren%2EforEach%28tsk%20%3D%3E%20%7B%0A%09%09%09if%20%28tsk%2EtaskStatus%20%3D%3D%3D%20Task%2EStatus%2EDueSoon%29%7B%0A%09%09%09%09parentProjects%2Epush%28tsk%2EcontainingProject%29%0A%09%09%09%7D%0A%09%09%7D%29%0A%09%7D%0A%7D%29%0Aif%20%28parentProjects%29%7B%0A%09document%2Ewindows%5B0%5D%2Eperspective%20%3D%20Perspective%2EBuiltIn%2EProjects%0A%09document%2Ewindows%5B0%5D%2Efocus%20%3D%20parentProjects%0A%7D%7Dcatch%28err%29%7Bconsole%2Elog%28err%29%7D

Assigning Tags to Tasks

The addTag(…) and addTags(…) function of the Task class are used to assign tags to tasks. These functions require object references to tags to add as the function input. Mu of both script is locating an existing tag object matching the provided tag name, and passing it to the tag assignment handlers.

tasks = document.windows[0].selection.tasks if (tasks.length > 0){ targetTagName = "Redwood" var targetTag = null tags.apply(function(tag){ if(tag.name == targetTagName){ targetTag = tag return ApplyResult.Stop } }) tag = targetTag || new Tag(targetTagName) tasks.forEach(task => task.addTag(tag)) }

Here’s a variation of the previous script that adds a set of tags to the selected tasks, after locating the task objects for the items in an array of tag names.

NOTE: in both examples, if a tag name can not be matched to an existing tag, a new tag using the tag name is created and added to the array.

tasks = document.windows[0].selection.tasks if (tasks.length > 0){ tagNames = ["Bow","Stern","Port","Starboard"] var tagRefs = new Array() tagNames.forEach(tagName => { var targetTag = null tags.apply(function(tag){ if(tag.name === tagName){ targetTag = tag return ApplyResult.Stop } }) tagRef = targetTag || new Tag(tagName) tagRefs.push(tagRef) }) tasks.forEach(task => task.addTags(tagRefs)) }
tasks = document.windows[0].selection.tasks console.log(tasks) //--> [object Task: TASK FOUR],[object Task: TASK TWO],[object Task: TASK ONE],[object Task: TASK THREE]
tasks = document.windows[0].selection.tasks tasks.forEach(action => console.log(action.name)) //--> TASK FOUR //--> TASK TWO //--> TASK ONE //--> TASK THREE
actionGroup = new Task("ACTION GROUP") tasks = document.windows[0].selection.tasks tasks.forEach(function(action){ console.log(action.name) moveTasks([action], actionGroup) })
/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.call-note-url", "version": "1.0", "description": "This action will open the URL string that is the value of the note of the selected action.", "label": "Open Note URL", "shortLabel": "Open Note URL" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ // action code // selection options: tasks, projects, folders, tags noteStr = selection.tasks[0].note if (noteStr.includes("://")){ URL.fromString(noteStr).call(()=>{}) } }); action.validate = function(selection, sender){ // validation code // selection options: tasks, projects, folders, tags return (selection.tasks.length === 1 && selection.tasks[0].note != "") }; return action; }(); _;

Plug-In: open link in note

This Omni Automaton plug-in will scan the note text of the selected project or task, and if it locates an URL in the text, will open the found URL.

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.call-note-url", "version": "1.1", "description": "This action will open the URL string that is the value of the note of the selected action.", "label": "Open Note URL", "shortLabel": "Open Note URL" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ var note = (selection.projects.length === 1 ? selection.projects[0].task.note : selection.tasks[0].note); if (note && note.includes("://")) { note.split("\n").some((line, index) => { if (line.includes("://")) { console.log("link found at index : " + index) URL.fromString(line.trim()).call(function(reply){}) return true } }) } }); action.validate = function(selection, sender){ // selection options: tasks, projects, folders, tags return (selection.projects.length === 1 || selection.tasks.length === 1) }; return action; }(); _;

Move Tasks

Here are two Omni Automation Plug-Ins for moving selected tasks into either a new task group or a new project.

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.move-selected-tasks-into-project", "version": "1.0", "description": "Move the selected tasks into a new top-level project.", "label": "Move Selected Tasks into New Project", "shortLabel": "Move Tasks" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ // selection options: tasks, projects, folders, tags // CONSTRUCT THE FORM var inputForm = new Form() // CREATE FORM ELEMENT: TEXT INPUT textField = new Form.Field.String("projectName", "Project Name", null) // CREATE FORM ELEMENT: OPTION MENU popupMenu = new Form.Field.Option( "projectType", "Project Type", [0, 1, 2], ["Parallel","Sequential","Single Actions"], 0 ) // ADD THE ELEMENTS TO THE FORM inputForm.addField(textField) inputForm.addField(popupMenu) // DIALOG PROMPT AND OK BUTTON TITLE let formPrompt = "Enter the name for the new top-level project and select its project type:" let buttonTitle = "Continue" // DISPLAY THE FORM DIALOG formPromise = inputForm.show(formPrompt, buttonTitle) // VALIDATE FORM CONTENT inputForm.validate = function(formObject){ // EXTRACT VALUES FROM THE FORM’S VALUES OBJECT textValue = formObject.values['projectName'] return ((textValue) ? true:false) } // PERFORM PROCESSES USING FORM DATA formPromise.then(function(formObject){ textValue = formObject.values['projectName'] menuItemIndex = formObject.values['projectType'] // CREATE PROJECT AND MOVE TASKS project = new Project(textValue) moveTasks(selection.tasks, project) // SET THE PROJECT TYPE if (menuItemIndex === 1){ project.task.sequential = true } else if (menuItemIndex === 2){ project.containsSingletonActions = true } // SHOW THE PROJECT projID = project.id.primaryKey urlStr = "omnifocus:///task/" + projID URL.fromString(urlStr).call(reply => {}) }) // PROCESS FORM CANCELLATION formPromise.catch(function(error){ console.log("form cancelled", error) }) }); action.validate = function(selection, sender){ // selection options: tasks, projects, folders, tags return (selection.tasks.length > 0) }; return action; }(); _;
/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.move-selected-tasks-into-new-action", "version": "1.0", "description": "Move the selected tasks into a new top-level action group.", "label": "Move Selected Tasks into New Action Group", "shortLabel": "Move Tasks" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ // selection options: tasks, projects, folders, tags // CONSTRUCT THE FORM var inputForm = new Form() // CREATE FORM ELEMENTS: TEXT INPUT textField = new Form.Field.String("groupName", null, null) // CREATE FORM ELEMENT: OPTION MENU popupMenu = new Form.Field.Option( "actionType", "Action Type", [0, 1], ["Parallel","Sequential"], 0 ) // ADD THE ELEMENTS TO THE FORM inputForm.addField(textField) inputForm.addField(popupMenu) // DIALOG PROMPT AND OK BUTTON TITLE let formPrompt = "Provide name and type for new top-level action group:" let buttonTitle = "Continue" // DISPLAY THE FORM DIALOG formPromise = inputForm.show(formPrompt, buttonTitle) // VALIDATE FORM CONTENT inputForm.validate = function(formObject){ // EXTRACT VALUES FROM THE FORM’S VALUES OBJECT textValue = formObject.values['groupName'] return ((textValue) ? true:false) } // PERFORM PROCESSES USING FORM DATA formPromise.then(function(formObject){ textValue = formObject.values['groupName'] menuItemIndex = formObject.values['actionType'] taskGroup = new Task(textValue) moveTasks(selection.tasks, taskGroup) // SET THE PROJECT TYPE if (menuItemIndex === 1){ taskGroup.sequential = true } // SHOW THE ACTION taskID = taskGroup.id.primaryKey urlStr = "omnifocus:///task/" + taskID URL.fromString(urlStr).call(reply => {}) }) // PROCESS FORM CANCELLATION formPromise.catch(function(err){ console.log("form cancelled", err.message) }) }); action.validate = function(selection, sender){ // selection options: tasks, projects, folders, tags return (selection.tasks.length > 0) }; return action; }(); _;

Display Host Project

If you have a project task selected, this plug-in will feature the containing project in the OmniFocus window:

/*{ "type": "action", "targets": ["omnifocus"], "author": "Otto Automator", "identifier": "com.omni-automation.display-host-project", "version": "1.1", "description": "This action will display the host project of the selected task.", "label": "Display Host Project", "shortLabel": "Display Project" }*/ var _ = function(){ var action = new PlugIn.Action(function(selection, sender){ // action code // selection options: tasks, projects, folders, tags project = selection.tasks[0].containingProject projID = project.id.primaryKey urlStr = "omnifocus:///task/" + projID url = URL.fromString(urlStr).call(function(reply){}) }); action.validate = function(selection, sender){ // validation code // selection options: tasks, projects, folders, tags return (selection.tasks.length === 1 && selection.tasks[0].containingProject) }; return action; }(); _;
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