Scripts

Please Note: Scripts are only available in the Diary++ version.

Script Basics

For those of you who want to get the JXCirrusDiary entries to do more than just their basic functions, or want to save time adding a few new functions to the user interface, there is a scripting language. Scripting is usually used to do two things:

JXCirrusDiary does not have its own special scripting language... It uses JavaScript (which may cause any web programmers reading this to breathe a sight of relief).

JavaScript is the programming language used in vast numbers of websites around the world to do lots of the more funky complex sort of things, like display maps that you can zoom in on. JXCirrusDiary uses the WebKit JavaScript engine - WebKit is the same engine that is used in the Chrome and Safari browsers.

There are 3 ways to specify scripts that can be run. You can:

Here are a couple of examples...

This script, called "MoreImportant" bumps up the priority for a task.

priority = JXGet("Priority");
priority++;
JXSet("Priority",priority);

The JXGet function gets the priority value from the task. The "priority++" line adds one to the priority. The JXSet function pushes the priority value back into the task. For more on modifying entries, see Modifying Entries.

This script, called "StartFirst" gives the user another user interface function - It lets them complete the current task, go to the most important task, and start work on that (all in a single mouse click).

JXGuiCall( "Complete");
JXGuiCall( "GoFirstTask");
JXGuiCall( "StartSession");

This script uses the JXGuiCall function, which sends commands back to the user interface. For more, see Controlling the User Interface.

Scripts in Entries

To add a a script to an entry, select Entry -> Edit. Once the Entry dialog appears, select the Scripts tab.

This page is split into 2 parts: The top part lists the scripts that you have added to this entry. The bottom part lists scripts that have been added to the Object Spec that this entry uses.

User-Defined Scripts

This list shows the name of the script, and the shortcut you can use to run each script.

Add- Lets you add a new script. It will open the Script Edit Dialog, which lets you type in the script.

 Edit- Lets you edit a script that you have already created. It also opens the Script Edit Dialog also.

 Delete - Lets you delete a script that you no longer want.

Double-clicking on a script in the list also edits the script.

Pre-Defined Scripts

This list shows you the scripts that have been defined in the object spec that this object uses. If you were to change the spec, this list may change to show a different list of scripts.

You can double-click the entries in the list to show what the script contains - It will open the Script Edit Dialog. These scripts are defined in the Object Spec, so you will need to go to the DB Schema dialog/Object Spec dialog to edit them.

Script Edit Dialog

This dialog allows you to edit the actual script.

Name - Contains the name of the script. The names have a couple of restrictions:

Shortcut - Shortcuts are typically 1 or 2 keystrokes that you can use to run a script using the keyboard only. To run the script, you would press Shift-M, then the keys that you define here.

Some examples:

Script Text - This is where you type in the actual script details.

 Refresh- You can use this to check for basic errors in your JavaScript. If you press it, and nothing happens, then your script looks OK. If there is an error, the error message will appear below the script text in a separate field (which goes away when there are no errors in the script).

OK - Finishes editing the script and saves the changes.

Cancel - Closes the window and discards any changes to the script.

Scripts in Object Specs

Scripts can be added to the Object Specs for a whole class of objects in the database.

The script itself is just added as extra text at the bottom of the spec. For example:

$<Priority> = init("5");
@Script MoreUrgent @Shortcut U
>"
  JXSet("Priority",Number(JXGet("Priority")+1));
"<;

The script is started after the "@Script" keyword. The name must appear next. If you want to use a shortcut for the script, add "@Shortcut" and then the shortcut keystroke. @Shortcut (and the key combination afterwards) are optional. See shortcut in the Script Edit Dialog section.

The script body appears between the >" and the "<;

When you add a script to an object spec, it will be available for any objects that use that spec. It will also be available for any object specs that inherit this one. One thing to note about inheritance: Lets say spec A defines a Blah script, and spec B inherits A. If B wants Blah to behave differently, then B can define its own Blah script. That will override the Blah script from spec A. This is very useful for triggers...

Global Scripts

As well as having scripts that are attached to a JXCirrusDiary entry, you can also have global scripts. These can be run from any entry in the diary. To create or edit global scripts, use Menu button then Global Scripts. This will bring up a dialog that is identical to the Scripts tab in the Script Edit Dialog.

Any scripts that you add in there will be available from all records in the database.

The Pre-Defined Scripts section here list global scripts that have been defined in the Database Schema. To add scripts in there, go to the schema, and add the scripts to the TopLevel object spec. Any scripts added to that will be global.

Running Scripts

There are 3 ways to run scripts:

Errors

If there is an error in a script, a notification message will appear at the top right telling you "Script errors in...". To go to the error, double click this message - It will take you to the script that has the error:

Modifying Entries

One of the main reasons for using scripts is to modify the values in an entry. To do this you will use:

JXGet("VARIABLE");

to get a value from an entry. For example:

score = JXGet("Score");

This will create a local script variable called "score" which contans the value from the Score field in the entry.

To get the values back into the entry, use

JXSet("VARIABLE",value);

For example:

JXSet("Priority",10);

will set the entry priority to 10.

Any variables that you define in the object spec for the entry will be able to be modified using JXGet and JXSet. The VARIABLE value will be the name of the value you have defined in the object spec (case sensitive).

The following table, list the standard system-defined variables for an entry.


Value Meaning Contents
Id
The ID number for the entry.

Title The title of the entry.
EntryType What type of entry this is. ToDo, Appointment, Journal, Object, Person, Household
Start_Time Start time for appointments and journals. Date in text form (see Dates).
End_Time End time for appointments and journals. Date in text form.
Start_After The start-after time for tasks. Date in text form.
Due_Date The due date for tasks. Date in text form.
Repeating Is this a repeating task. 0 (if No), 1 (if Yes)
Repeat_Start The start-after date to repeat from. Date in text form.
Repeat_Due The due date to repeat from. Date in text form.
Begin_Repeating The date to begin the task repeating from. Date in text form.
Finish_Repeating The date after which the task stops repeating. Date in text form.
Exclude_Repeating A set of dates where the task will not repeat. Date in text form.
Duration The expected duration of a task. In the form HH:MM:SS.
Remaining
The remaining duration of a task (calculated using duration and percentage complete).   Read only value.
In the form HH:MM:SS
Spent
The total time spent on a task.   Read only value.
In the form HH:MM:SS
Complete The completion percentage of a task. 0-100.
Priority The priority of the task. 0-300.
Depend_Title The title of another entry this depends on.
Prevent_Other_Depend Prevent other tasks from depending on this 0 (if No), 1 (if Yes).
Prevent_Depend Prevent this from depending on others. 0 (if No), 1 (if Yes).
Resource The name of the resource assigned to this task.
TimeType The time type we are using for this task.
Baseline_Duration The baseline set for the task duration. In the form HH:MM:SS.
Baseline_Start The baseline start time. Date in text form.
Baseline_End The baseline end time. Date in text form.
Baseline_Progress Are we tracking progressive baselines. 0 (if No), 1 (if Yes).
Auto_Baseline Should we adjust the baseline automatically. 0 (if No), 1 (if Yes).
Command Any commands to be executed.

Whether these can all be set will depend on whether the variable is set to eval in the object spec. If it is set to eval, then there is no sense in trying to set it from a script, because it will just get overridden.

In addition to changing the variables, you can also change the object spec for an entry. Use:

JXSetSpec("SPEC");

SPEC is the new spec that you will use.

NOTE: You can only set the spec to something else that inherits off the same base object spec. If you don't understand what this is talking about, best avoid JXSetSpec for now.

Controlling the User Interface

The other big helpful thing that scripts can do is to send commands back to the user interface. This is done using:

JXGuiCall("FUNCTION");

FUNCTION is the function on the GUI that you want to call.

For example, you could go to the first task:

JXGuiCall("GoFirstTask");

Some GUI calls can take parameters.

JXGuiCall("Query","MyQuery");

IMPORTANT: When you call a GUI function, that function works on the diary entry that is selected in the GUI.   For example, you could have a script that automatically starts the highest priority task.

JXGuiCall("GoFirstTask");
JXGuiCall("StartSession");

In this case, it wouldn't matter what entry you had selected - It would always start the highest priority task.   That is because "GoFirstTask" changes the selected entry on the GUI.

This behaviour is different to JXGet and JXSet - They always work with the entry that the macro is part of.


Here is a full list of the GUI functions you can access:


Function Menu Equivalent Meaning
Edit Entry -> Edit Edit the selected item.
EditEntry
Entry -> EditEntry
Edit the entry (even if a a time slot is selected).
EditID
(no equivalent menu item)
Edits an entry with a given ID. Should use ID as a parameter 1 i.e: JXGuiCall("EditID",12345);
Copy Edit -> Copy Copies the entry to the clipboard.
CopyID
(no equivalent menu item)
Copies an entry with a given ID. Should use ID as parameter 1 i.e. :JXGuiCall("CopyID",12345);
Cut Edit -> Cut Cuts the entry and stores on the clipboard.
CutID
(no equivalent menu item)
Cuts an entry with a given ID.   Should use ID as parameter 1 i.e. :JXGuiCall("CutID",12345);
Paste Edit -> Paste Pastes the entry from the clipboard in the selection location.
Paste-As Edit -> Paste As Pastes the entry from the clipboard and changes to a different type.
Delete Edit -> Delete Deletes the selected entry.
Complete Entry -> Complete Marks the task or appointment as complete.
Compact
Entry -> Compact
Compacts the entries from this one down the tree.
Link
Entry -> Link
Links the entries so they depend on each other.
Postpone Entry -> Postpone Pops up the dialog to allow the entry to be postponed.
PostponeDay Entry -> Postpone Day Postpones the entry by one day.
AdjComplete Entry -> % Complete Pops up the dialog to adjust the % completion for a task.
BaselineHours Entry -> Baseline Hours Saves the baseline hours for a task.
BaselineDate Entry -> Baseline Hours Date Saves the baseline hours, start and end date.
AddEntry
Edit -> Add
Adds a new top level entry.
AddTask
Add -> Add Task
Adds a new task.
AddJournal
Add -> Add Journal
Adds a new journal entry.
AddAppointment
Add -> Add Event
Adds a new event.
AddPerson
Add -> Add Person
Adds a new person.
AddAddress
Add -> Add Address
Adds a new address.
AddPlace
Add -> Add Place
Adds a new place.
Note
Add -> Add Note
Adds a new quick note.
Parameter 1 - The text of the note.
CreateChild Entry -> Create Child Creates a child of the current entry.
CreateSibling Entry -> Create Sibling Creates a sibling of the current entry.
StartSession Entry -> Start Session Starts a session for the selected entry.
StopSession Entry -> Stop Session Stops the running session.
CompleteSession Entry -> Complete Session Mark the running session task/appointment as complete.
AddSession
Similar to timesheet function
Adds an entry to the time spent for a task for that person.
Parameter 1 - The day of the session (i.e. "Today", "Yesterday", "1-Mar-2013" ).   If you specify a time, then the session will be recorded for exactly that time (i.e. "Yesterday 1:00PM").
Parameter 2 - The duration of the session (i.e. "1:00", "0:30" ).
Parameter 3 - The name of the resource doing the work.
ClearSession
Similar to timesheet function. Clears all time spent entries for a task for a day.
Parameter 1 - The day of the session (i.e. "Today", "Yesterday", "1-Mar-2013" ).
Parameter 2 - The name of the resource doing the work.
RepeatInstance
Entry -> Repeat to Instance
Converts a single instance of a repeating task or event to an actual task/event.
Plan Planning -> Plan Time Starts the dialog to plan time for an entry.
MovePlanUp Planning -> Move Plan Up Moves the selected plan earlier in the day.
MovePlanDown Planning -> Move Plan Down Moves the selected plan later in the day.
LockSession Planning -> Lock Session Turns a selected session into a plan.
LockTaskDay Planning -> Lock Task For Day Turns all sessions for a task into plans just for the current day.
LockTaskAll Planning -> Lock Task All Turns all sessions for a task into plans.
LockDay Planning -> Lock Everything for Day Locks all sessions as plans for today (for all tasks).
LockAll Planning -> Lock Everything Locks all sessions in the diary.
UnlockTaskDay Planning -> Unlock Task For Day Removes all plans for a task for today only.
UnlockTaskAll Planning -> Unlock Task All Removes all plans for a task.
UnlockDay Planning -> Unlock Everything for Day Removes all plans for today.
UnlockAll Planning -> Unlock Everything Removes all plans.
CommandRun Entry -> Command Run Runs the selected command.
CommandRunAll Entry -> Command Run All Runs all commands for the entry.
CommandSkip Entry -> Command Skip Skips the selected command.
CommandClear Entry -> Command Clear Marks the selected command as not run.
CalNextDay Calendar -> Next Day Moves the calendar to the next day.
CalLastDay Calendar -> Previous Day Moves the calendar to the previous day.
CalNextWeek Calendar -> Next Week Moves the calendar to the next week.
CalLastWeek Calendar -> Previous Week Moves the calendar to the previous week.
CalNextMonth Calendar -> Next Month Moves the calendar to the next month.
CalLastMonth Calendar -> Previous Month Moves the calendar to the previous month.
CalNextYear Calendar -> Next Year Moves the calendar to the next year.
CalLastYear Calendar -> Previous Year Moves the calendar to the previous year.
CalToday Calendar -> Today Moves the calendar to today.
CalGoDate Calendar -> Go To Date Pops up a dialog to prompt to go to a specific date.
GoSession Go -> Current Session Goes to the task that has a session.
GoFirstTask Go -> First Task Goes to the highest priority task.
GoNextTask Go -> Next Task Goes to the next task (in priority order).
GoLastTask Go -> Previous Task Goes to the previous task (in priority order).
GoFirstPlan Go -> First Plan Goes to the earliest planned session.
GoNextPlan Go -> Next Plan Goes to the next plan (in chronological order).
GoLastPlan Go -> Previous Plan Goes to the previous plan.
GoID
(no equivalent menu item)
Select an entry with a given ID.   Should use ID as parameter 1 i.e. :JXGuiCall("GoID",12345)
Refresh View -> Refresh Refreshes the current display.
Find Edit -> Find Finds a given piece of text. You can supply the text to search for as parameter 1.
Recalculate View -> Recalculate Performs a full recalculate, including all sessions.
CloseTab View -> Close Tab Closes the current tab (if it is a query or timesheet).
Collapse View -> Collapse Tree Collapses the entire tree.
Expand
View -> Expand Tree
Expands the full tree below the selected item.
TreeView View -> Tree Switch to the tree view.
PlanView
View -> Plan
Switch to the plan view.
DayView View -> Day Switch to the day view.
WeekView View -> Week Switch to the week view.
MonthView View -> Month Switch to the month view.
SummaryView View -> Summary Switch to the summary view.
PlanningView
View -> Planning
Switch to the planning view.
ProjectView
View -> Project
Switch to the project view.
FocusView
View -> Focus
Switch to the focus view.
TimesheetView
Tools -> Timesheet
Open the Timesheet view (or switch to it if it is already open).
Query Query Run a query and display the results. Should use query name as parameter 1, ("Query", "QueryName"). If there are extra values, supply them as parameters 2, 3 and 4.
ExportTree
File -> Export -> Tree
Exports the tree view to a CSV file.   Parameter 1 is the name of the file to export to.  Parameter 2 is the maximum depth in the tree to export (0 = All levels).
ExportQuery
File -> Export -> Query
Exports the current query to a CSV file.   Parameter 1 is the name of the file export to.
Import
File -> Import -> Tasks
Imports CSV data from a named template.  The template name should be the same as a saved import template.   If no name is specified, then it will just open the Import Tasks dialog.

Prompting

JXCirrus' scripting provides a several ways to prompt the user to enter values:

The following example prompts the user to update their name.

var name = JXGet("Name");
name = JXPromptText("Enter your name...",name); JXSet("Name", name);

JXPromptText takes 2 parameters:

  1. The prompt to display on the popup dialog.
  2. The value to initially put into the form.

Another popup dialog type gives the user a list of values they can choose from a dropdown.

var animal = JXPromptChoice( "Select an animal...", "Tiger,Lion,Zebra,Salamander", "Lion", true );
JXPromptChoice takes 4 parameters:
  1. The prompt to display on the popup dialog.
  2. The set of choices to display, separated by commas.
  3. The choice to select initially.
  4. Can the user enter a different value to these choices.

Another related prompt dialog is able to prompt based on values that are already in the database.

var person = JXPromptDB( "Select a co-worker...", "Worker", "Name" );

What the example above will do is pop up a dialog where the user can choose values from a drop-down list.   The values come from the "Worker" object spec, and the "Name" variable.
JXPromptDB takes 5 parameters:

  1. The prompt to display on the popup dialog.
  2. The name of the object spec to take the values from.
  3. The name of the variable within the object spec to take the values from.
  4. The choice to select initially.
  5. Can the user enter a different value to these choices.

There are 2 special cases that you can use for this dialog - If the object spec name is set to "SYSTEM":

  1. If the variable name is "PEOPLE", then it will fill the list with any entries that are classed as a person.   The title value that is shown in the tree view will be shown in the choices list.   It also includes any resources (see next item).
  2. If the variable name is "RESOURCES", then it will fill the list with the names of all resources stored in the system.

Searching

It is possible to search for values within the database using simple pattern matching.   Here is an example:

var pattern = JXPrompt("Search for","");
var results = new Array();
results = JXSearchDB( "Task", "Title", pattern );

This lets the user search for whatever was entered into the "pattern" variable.   It will search in objects with object spec "Task" and in the "Title" variable.

The parameters for JXSearchDB are:

  1. The object spec name to match in (or "*" for all object specs).
  2. The variable name for values to match in (or "*" for all variables in an object).
  3. The pattern to match - You can use basic wildcards (i.e. "*Move" would match "Now Move", but not "Moving").

Trigger Scripts

Trigger scripts are scripts that are run automatically when some event happens in the system, such as completing a task.

In this example, lets say we want a repeating task that happens less frequently each time you run it. In the object spec, we have a variable called "Frequency" which defines how many days till the task runs again. It might look something like this:

$<Frequency> = init("1");
$<Repeat_Start> = eval("+$<Frequency> days 9AM");
$<Repeat_Due> = eval("+$<Frequency> days 5PM");

Now, we can adjust frequency each time the task is complete.

@Script on_complete
>"
  freq = JXGet("Frequency");
  freq++;
  JXSet("Frequency",freq);
"<;

Trigger scripts always start with "on_" - If you start a script with "on_" it will NOT appear in the list of scripts or on the toolbar, and shortcut keys will have no effect. This is because these are tied to other things that happen in the system...


Trigger Called
on_start When a session is started for the entry.
on_stop When a session is stopped for the entry.
on_complete When a task or appointment is marked as complete.
on_reopen
When a task or appointment is reopened from complete.
on_create When an entry is created.
on_edit Called after an entry has been edited. This is useful if you have some value in your entry that needs to be automatic, but you don't need it to slow down the system by being recalculated all the time.
on_recalculate Called when the user triggers a full recalculate on the system. This will NOT happen during a background recalculate. Useful if you want to do a one-off change to a whole lot of entries.
on_startup
Called when the application first starts up.   This is not called at any other time.

Calling Other Scripts

It is possible for one script to call another script in the same object, or elsewhere in the diary.

JXCallSelf("Script");

This calls a script in the same object. For example, this calls the "LessFrequent" script:

JXCallSelf("LessFrequent");

JXCallParent("Script");

This calls a named script in the parent object of this one.

JXCallChild("Script","ChildName",ALL);

This calls a named script on a given child.

For example, if we had in the object spec:

$[Task] = ${MyTask}[];

and MyTask has a script called DoIt, we could use:

JXCallChild("DoIt","Task",1);

This will call DoIt for all of the children in the "Task" group.

If we only wanted to call DoIt for the first one, then we would use

JXCallChild("DoIt","Task",0);

JXCallAll( "Script", ALL );

JXCallAll("Script",ALL);

This just searches through the whole diary and runs any scripts that have than name. If ALL is 1, then it runs all of that script. If ALL is 0, then it will stop after it finds the first one. ALL means call for all children..

JXCallID( "Script", id );

This calls a script on an object with a specific ID.

var results = new Array();
results = JXSearchDB("Task","Title","Sleep");
for( int i = 0; i < results.length; i++ )
{
  JXCallID( "Wake Up", results[i]);
}

This will call the Wake Up script for all entries with spec Task and Title = Sleep.

Date Functions

JXDateCompare(Date1,Operation,Date2);

This compares 2 dates. It returns 1 if the operation is true. The operation can be one of "==", "<=", "<", ">", ">=".

JXDateEval(Date);

This returns an expanded form of a date - For example JXDateEval("Tomorrow 11AM") will return "Tue 15-Nov-2011 11:00" (assuming today is 14-Nov-2011). See below for an example...

This makes sure the start date is greater than the due date. If it isn't, it sets it to the start date +1 day.

if( JXDateCompare( JXGet("Start_After"), ">", JXGet("Due_Date") ) )
{
  JXSet("Due_Date",JXDateEval(JXGet("Start_After") + "+1 day" ) );
}

Other Functions

JXOpenUrl(Url);

This function can open a web URL, or even another application that can be opened via URL link.
JXOpenUrl("https://www.google.com");