This page documents the API for interacting with fields and the global objects in flows.
In general flows are JavaScript code and thus any valid JavaScript is allowed. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript for a JavaScript intro. The objects Inputs, Fields and all the rest of the modules listed below are made available for all flows s.t. they can be accessed in the JavaScript code.
We include the utility library lodash 4.7.10 in all flows. See https://lodash.com/docs the available functions.
There is also a tutorial to the Cuesta tool which also contains a few examples of flows. It is highly recommend that you go through the tutorial before diving into this reference documentation.
Inputs to a flow can be accessed via the Inputs array. Inputs are generally strings.
var mi = Inputs["myinput"];
Fields can be accessed via the Fields object. Each field has a number of methods - it may not always make sense to invoke a given method on a field.
Will click on the given field.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).Fields["mybutton"].click();
// With an optional 500 ms deadline
Fiels["mybutton"].click({ deadline: 500 });
Will click on the given field offset by the amount given. It allows you to e.g. click in the middle of a table row or the corner of a button.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.// Click myButton 10px from top and 10px from left
Fields["mybutton"].clickWithOffset(10, 10);
Will simulate a mouse-click on the given field. The difference between simulate-click and click is only relevant for Java applications where mouse-events can be generated directly (click) or as a series of injected events - mousedown, mouseclicked, mouseup (simulateClick).
Fields["mybutton"].simulateClick();
Will click on the given field offset by the amount given. It allows you to e.g. click in the middle of a table row or the corner of a button.
// Click myButton 10px from top and 10px from left
Fields["mybutton"].simulateClickWithOffset(10, 10);
Will right-click on the given field.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.Fields["mybutton"].rightClick();
Will click on the given field offset by the amount given. It allows you to e.g. click in the middle of a table row or the corner of a button.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.// Click myButton 10px from top and 10px from left
Fields["mybutton"].rightClickWithOffset(10, 10);
Will double-click on the given field.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.Fields["mybutton"].doubleClick();
Will click on the given field offset by the amount given. It allows you to e.g. click in the middle of a table row or the corner of a button.
options an optional options object, supports;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller. The use-case for the deadline parameter is for example if the click launches a dialog which blocks the thread, then setting a deadline allows the flow to continue even though the click is technically not done.// Click myButton 10px from top and 10px from left
Fields["mybutton"].doubleClickWithOffset(10, 10);
Click in a cell in table (only applicable for tables).
rowMatch a text to match in the rowcolMatch a text to match in a column headeroptions an options object on which the follow properties can be set;
deadline the time in ms to wait for the click to fail/succeed. If the click takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller.reflectionDepth indicates how deep to do the search for the rowMatch value (also see Reflection depth)useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).// Click in the cell defined by its row containing 'A' and its column (header) containing 'B'
Fields["myTable"].clickCell('A', 'B');
// The same command but use reflection depth to do a deeper search
Fields["myTable"].clickCell('A', 'B', { reflectionDepth: 2 });
Will read the value of the field. Depending on the type of the field the behavior will differ, e.g. on a label it will return the text content of the label, for a text-field it will return the contents of the text-field. For a more complex container type it will return a JSON representation of the control (which can be natively accessed in the flow as an object). See JSON serialisation for details on how different types are serialised.
options an optional options object with details regarding the inspection.
useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).var contents = Fields["mytextfield"].read();
Returns true if the field could be found.
if(Fields["mytextfield"].exists()) {
...
}
Inspect a given field. The returned object will contain misc information about the field - the type of information depends on the type of the field.
options an optional options object with details regarding the inspection.
useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).reflectionDepth (see below)You can optionally obtain more detailed information about the data in eg treeviews. To do this, pass a positive reflectionDepth value as shown in the examples below.
As an example, reflectionDepth: 3 means the result includes fields such as arrival.date.day (3 steps) but not eg patient.eyes.left.tla (4 steps).
The reflectionDepth paramater affects the data available in the output under the objects in the control in question (eg treeview nodes). The main use of
this feature is to determine which patterns to use with Field['field'].select() when simply selecting the rendered text doesn’t work.
var info = Fields["mytextfield"].inspect();
// See which information was returned
Debug.showDialog(JSON.stringify(info));
// If info has a `text` property, then this will show the text
Debug.showDialog(info.text);
var detailedInfo = Fields["myTreeView"].inspect({ reflectionDepth: 2});
// This object includes extra data under the nodes of 'myTreeView'.
Debug.showDialog(JSON.stringify(detailedInfo));
Input a text value into a textfield/textbox/etc.
text the text to inputoptions an optional options object with details regarding the inspection.
useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).Fields["mytextfield"].input("some text");
Inputs text into a field using native events, i.e. simulating keyboard input. This is useful for fields which does validation (e.g. date-fields or similar). Use only if the input method does not work.
text the text to input - you can use <backspace> to indicate a backspace/delete actionFields["mydatefield"].inputNative("11112011");
Fields["mydatefield"].inputNative("123<backspace>"); // field will contain '12'
Inputs text into a field using native events with a given delay between each keystroke simulating keyboard input. This is useful for fields which does validation (e.g. date-fields or similar). Use only if the input method does not work.
text the text to inputdelay the number of milliseconds to wait between each “keystroke”Fields["mydatefield"].inputNativeWithDelay("some text", 100);
Select a value. This only works for dropdowns, listboxes and tree-views.
Note that for tree-views the value given to this function may be an expression which matches the path to a leaf. E.g. for the following tree:
tree
├── a
│ └── b
│ └── c
├── d
└── x
└── y
The node c may be selected by:
Fields["tree"].select("a/b/c");
value the value to select. By default value is treated as a regular expression, where characters like ., * and ( have special meaning. If you want a literal match you need to surround value with << and >>, e.g. select('<<'+v+'>>') where v is the literal value to match.options an optional options object with details regarding the selection.
deadline the time in ms to wait for the select to fail/succeed. If the select takes longer than the deadline to fail or succeed it will be reported as succeeding to the caller.reflectionDepth an option indicating how far the select matching should dive into java objects (eg treeview nodes). Setting this too high may negatively affect performance. Defaults to 0. Use the inspect method to determine how to match against this information and what an appropriate (minimal) reflection depth is.useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).// Select "option1" and use reflectionDepth to to try and find "option1"
Fields["mytree"].select("option1", { reflectionDepth: 2 });
Select a value based in an index. This only works for dropdowns, listboxes and tree-views.
index is the index in the combo, listbox or tree to select.options an optional options object with details regarding the selection.
useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).Fields["mycombo"].selectIndex(5);
Select a value (with an offset). This only works for dropdowns, listboxes and tree-views.
value the value to base selection on. The value needs only to partially match the shown option to be selected, e.g. using “utte” in a list containing the item “butter” will select it.offset (int) the offset which will be used to do actual selection. E.g. if “1” then the next element (which was found using value will be selected).Fields["mytree"].selectWithOffset("option1", 1);
Select a value (with an offset and skip). This only works for dropdowns, listboxes and tree-views.
value the value to base selection on. The value needs only to partially match the shown option to be selected, e.g. using “utte” in a list containing the item “butter” will select it.offset (int) the offset which will be used to do actual selection. E.g. if “1” then the next element (which was found using value will be selected).skip will select the N’th match to start from. E.g. 1 will skip the first match and select the 2nd.Fields["mytree"].selectWithOffsetAndSkip("option1", 1, 1);
If used on e.g. a combobox with options; [“option1”, “option2”, “option1”, “option3”] the code-fragment above will select “option3”. This is done by first looking for all “option1”s. Then skip 1 this will get you the 2nd “option1”, then offset by 1 which will get you “option3”.
Can be used in a table to edit a given cell.
row the row in which to find the cell (match any cell in the row)column the column in which to find the cell (must match a single column)value the value to put into the cell (works with textfield and dropdowns)options is an optional argument, which can contain:
reflectionDepth used to finding the value if there is e.g. a combobox in the cell to edit (also see Reflection depth)useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).Given the following table:
| header 1 | header 2 |
|---|---|
| cell 1 | cell 2 |
| cell 3 | cell 4 |
This command:
Fields["mytable"].editcell("cell 3", "header 2", "boom");
Will result in this table:
| header 1 | header 2 |
|---|---|
| cell 1 | cell 2 |
| cell 3 | boom |
Highlight the given field with the default color.
Fields["myfield"].highlight();
Highlight the given field with the given color. Available colors are red, green and blue.
color the highlighting color - red, green or blue.Fields["myfield"].highlightWithColor("blue");
Cancel a highlight on a field.
Fields["myfield"].lowlight();
The global objects listed below are available in all flows.
The dialog object contains methods for presenting the user with information or requesting information from the user at runtime.
Shows a blue information dialog with an OK button. The flow does not proceed until the user has clicked OK. Options is an optional parameter.
header is the title of the dialogtext is the text content shownoptions is a JavaScript object, supported properties:
buttons is an array of buttons to display in the bottom part of the dialogtimeout an int determining when the dialog should auto-closesound a string (one of asterisk, beep, exclamation, hand, question) which indicates a system sound to play once the dialog is shownThe buttons array consists of button objects with the following properties:
value the text to display on the button (should be unique for a dialog)isDefault (boolean) a true/false value indicating whether or not this button is the default (i.e. will be activated on the enter-key) - should only be set to true for one button per dialog – default is falseisCancel (boolean) indicating whether or not the button should cancel the dialog – default is false
The default value for buttons is an “OK” button:
[
{ 'value': 'OK' }
]
The button clicked will be available as a property named button on the return value from the dialog. If the user clicks a cancel button then an exception is thrown.
Dialog.info("Hello", "This is some text to be shown.", {});
With options:
Dialog.info(
"Hello",
"Some text - I will max be shown for 10 secs.",
{ timeout: 10 }
);
With pre-defined buttons:
var r = Dialog.info(
"Hello",
"Do you want to continue",
{ timeout: 10
, buttons: [
{ 'value': 'No', 'isCancel': true },
{ 'value': 'Maybe' },
{ 'value': 'Yes' },
]
}
);
if (r.button == 'Yes') {
// user answered yes - we can continue
...
}
Shows a red warning dialog to the user with an OK button. Similar to the info dialog, but red. Options is an optional parameter.
header is the title of the dialogtext is the text content shownoptions is a JavaScript object, supported properties:
buttons is an array of buttons to display in the bottom part of the dialog (see info-dialog for further information)timeout an int determining when the dialog should auto-closesound a string (one of asterisk, beep, exclamation, hand, question) which indicates a system sound to play once the dialog is shownDialog.warn("Warning!!", "This is some text to be shown. Consider yourself warned.");
Shows a dialog into which the user may input data. The type of data which can be input is determined by the options parameter.
header is the title of the dialogtext is the text content shownoptions is a JavaScript object which determines the input the user should provide. Each property on the object is one input the user must provide. The name of each property is used when returning the results. Each input should contain the following variables:
buttons is an array of buttons to display in the bottom part of the dialog (see info-dialog for further information)type to determine which UI element to display, TEXT, PASSWORD, FILE, SELECT, RADIO, DATE, MULTITEXT, TYPEAHEAD, HEADER, DIVIDER and DESCRIPTION are the supported options - see options for each type belowmaxDialogWidth/maxDialogHeight (int) change the default maximum width and height for the window,dependsOn is an expression that determines when this input should be shown. You can either specify the name of another property - in which case the input will be shown if the other property has a value, or you can specify a <name-of-other-property>=<value> type string - in which case the input will be shown if the other property has the given value. If dependsOn is empty the input will always be shown. Using a ~ instead of = in the expression will cause the value to be interpreted as a regular expression (from 1.8.0).promptWidth sets the with of the label/promptsubmitOnValidation is a boolean flag that determines whether or not the dialog will be automatically submitted when all fields validate - or notsound a string (one of asterisk, beep, exclamation, hand, question) which indicates a system sound to play once the dialog is shownbuttons is an array of buttons to display in the bottom part of the dialog (see info-dialog for further information)Further options depends on the value of type:
prompt is the text which is displayed as an hint to the user for this option.promptAlignment is the alignment the prompt should follow. Available options are: “Center”, “Justify”, “Left” (default), “Right”.value is an optional default value for the input.prefix and suffix are texts to be shown before and after the input field.focus is whether to focus this field - if multiple fields have focus set to true then the last one will be focused.multiline whether multiple lines are allowed (default false).validation is a validation object (see below).prompt is the text which is displayed as an hint to the user for this option.value is an optional default value for the input.focus is whether to focus this field.validation is a validation object (see below).prompt is the text which is displayed as an hint to the user for this option,value is an optional default value for the input,selected is whether or not the option starts out as selected (checked) or not - only applicable for SELECTselectBetween is a array of strings which determines the available dropdown options if the type has value SELECT,focus is whether to focus this fieldvalidation is a validation object (see below).value is used as the text displayed.texts is an array of text inputs to show - each input may have the following properties set;
name is used to refer to the input,prefix and suffix are texts to be shown before and after the input field,value is the default value,multiline whether multiple lines are allowed (default false)focus is whether to focus this fieldvalidation is a validation object (see below).selectFrom is the construction which determines what the user is able to select from.The value of selectFrom can be a list of strings in which case the list is simply displayed. E.g.:
...
myProp: {
type: 'TYPEAHEAD',
selectFrom: ['Option 1', 'Option 2']
}
...
It can be a list of objects with a value or display property that is displayed for the user. As in the example below where the user can select or get auto-completion on ‘a’ and ‘b’.
...
myProp: {
type: 'TYPEAHEAD',
selectFrom: [
{display: 'a', id: 100},
{display: 'b', id: 100}
]
}
...
The value of the myProp property after the input dialog is completed will be the full object selected, e.g. {display: 'a', id: 100}.
You can also supply arbitrary objects and a formatting string.
...
myProp: {
type: 'TYPEAHEAD',
selectFrom: {
format: '{{foo}} with id {{id}}',
items: [
{foo: 'a', id: 100},
{foo: 'b', id: 100}
],
}
}
...
This will display e.g. “a with id 100” in the suggestion dropdown. The object selected will be available in the myProp property (not just the formatted string). In addition to the format string, you can also set the following options:
minInputLength the minimum number of characters the user must input in order to get suggestionsfilterMode which mode should be used to filter the suggestions; select from 'contains', 'startswith', 'endswith'.A callback function can also be used. The function supplied will get invoked with the string entered by the user. E.g.:
...
myProp: {
type: 'TYPEAHEAD',
selectFrom: {
format: '{{foo}} with id {{id}}',
items: function(searchString) {
return [
{foo: 'a', id: 100},
{foo: 'b', id: 100}
];
},
}
}
...
In this case we’re not using the input for anything but other cases might do so, like when fetching options from e.g. a remote resource (via http or similar).
Lastly, the contents of a Table can be used as options.
...
myProp: {
type: 'TYPEAHEAD',
selectFrom: Table.map('nameOfTable', 'propToIndexBy').selectFrom('{{foo}} with id {{id}}')
}
...
This will use the table rows and generate a formatted string for each row - the result will again be an object representing the row.
The DIVIDER type does not support any options.
Input fields may have a validation object in their options which determines valid values for the inputs. The validation object has the following properties;
isRequired boolean value indicating whether a value must be supplied for the field,regex is a regular expression which must match the given input in order for the field to validate,message is an optional message to be displayed in case validation fails.Use either isRequired or regex, not both at the same time.
var result = Dialog.input(
'This is a demo',
'Some description goes here.', {
'submitOnValidation': true,
'maxDialogHeight': 1000,
'maxDialogWidth': 2000,
'name': {
'prompt': 'Name',
'type': 'TEXT',
'suffix': 'mm'
},
'colorRadio': {
'prompt': 'Choose color',
'type': 'RADIO',
'selectBetween': ['red', 'green', 'blue']
},
'foo': {
'prompt': 'Show only on blue',
'dependsOn': 'colorRadio=blue',
'type': 'TEXT'
},
'colorCombo': {
'prompt': 'Choose color',
'type': 'SELECT',
'selectBetween': ['red', 'green', 'blue'],
'validation': {'isRequired': true, 'message': "Color must be selected"}
},
'header' : {
'type': 'HEADER',
'value': 'Header #1'
},
'desc': {
'type': 'DESCRIPTION',
'value': 'Super long description possible. When a moon hits your eye like a big pizza pie. Thats amore. When the world seems to shine like youve had too much wine. Thats amore. Bells will ring ting-a-ling-a-ling, ting-a-ling-a-ling. And youll sing Vita bella. Hearts will play tippy-tippy-tay, tippy-tippy-tay'
},
'date': {
'type': 'DATE'
},
'multi': {
'type': 'MULTITEXT',
'prompt': 'Some complex texts',
'texts': [
{ 'name': 'a', 'prefix': 'pre', 'suffix': 'suf', 'validation': { 'regex': 'a+', 'message': 'Must contain at least one \"a\"' } },
{ 'name': 'b', 'prefix': '>', 'suffix': '<' }
]
}
}
);
// Now use the input values for something
var name = result.name;
var eyecolor = result.colorRadio;
This will result in the dialog shown below.
In addition to the normal native input function we also support using HTML input forms. This approach does not bring as much built-in functionality - validation, conditional displays etc - but offers a larger degree of customization in the appearance of the displayed form. It works by taking the form, either HTML directly or a URL to a page containing the form and then displaying this in a dialog. When the user accepts the form (clicks “ok”) the page is parsed and information about the contents of the individual fields are extracted for use in the flow.
The input values entered can be retrieved from the dialog result by using the name or id property of the input element. For more info on forms see e.g. https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms. For a concrete example with a number of different input elements see e.g. http://sirenia.eu/tutorial/form.html.
header - [string] the header to displaytext - [string] a longer text to displayoptions - [object] containing options for the dialog itself:
source - [string] the form to display - either HTML directly or a URLembed - [bool] if true, manatee will add some styling and html/body tags to the page, if false nothing is addedmaxDialogWidth - [int] the max width the dialog must takemaxDialogHeight - [int] the max height the dialog must takeSource directly as an option.
var result = Dialog.inputHtml(
'Header',
'Some more text',
{
source: "<input type='text' id='myText'></input>",
embed: true
});
// The result will have a `myText` property since we added the `id` property with the value to the input field
Debug.showDialog("Result was "+result.myText);
Using a remote document.
var result = Dialog.inputHtml(
'Header',
'Some more text',
{
source: "http://sirenia.eu/tutorial/form.html",
embed: true
});
// The result will have a `myText` property since we added the `id` property with the value to the input field
Debug.ger(result);
The flow object provides a mechanism to invoke other flows. This allows some flows to become superflows connecting multiple flows together. Flows from other applications may also be invoke in this fashion.
You can use the include(...) method to include code from a MODULE typed flow. This is great if you have some code that you want to share between multiple flows.
The code in the module flow can export its functionality by assigning variables to the global exports object. See the example below.
name the name or subject of the module to includeWe’ll define a handy math module (given the subject = math):
var times = function(a, b) {
return a*b;
}
var plus = function(a, b) {
return a+b;
}
var bigNumber = 10000;
exports.times = times;
exports.plus = plus;
exports.bn = bigNumber;
and this can then be used in another flow:
var math = Flow.include('math');
var ten = math.times(2, 5);
Run another flow with the run(...) method. You provide the input to the flow and will get the outputs of the flow.
name the name of the flow to run - if there are 0 or more than 1 flow with this name an Error will be thrownenvironment is a JavaScript object containing the input to the flow. Each property on the object will be mapped to an input. Currently only string values are supported. Inputs are accessed in the running flow with Inputs["<inputname>"] e.g. Inputs["myinput"] or simply <inputname> e.g. myinput (if the var result = Flow.run("MyOtherFlow", { "inputA": "AAA", "inputB": "BBB" });
// "MyOtherFlow" will now get executed, the inputs may be accessed via e.g. Inputs["inputA"] in "MyOtherFlow"
var outputC = result.outputC; // providing "MyOtherFlow" has a defined output called "outputC"
It is possible to chain flows like:
var result = Flow.run("RunLast", Flow.run("RunFirst", {}));
Wait the given amount of seconds.
timeout the number of seconds to waitWait.forSeconds(2);
Wait the given amount of milliseconds.
timeout the number of milliseconds to waitWait.forMilliseconds(200); // Wait for 0.2 seconds
Wait for the given field to appear - will return when field appear or throw an exception when the given amount of seconds has elapsed.
field the field to wait for e.g. Fields["myfield"]timeout the max amount of seconds to wait for the field to appearWait.forField(Fields["myfield"], 10);
Wait for the given field to disappear - will return when field disappears or throw an exception when the given amount of seconds has elapsed.
field the field to wait for e.g. Fields["myfield"]timeout the max amount of seconds to wait for the field to disappearWait.forFieldToDisappear(Fields["myfield"], 10);
The Xml module enables parsing information stored in local or remote xml files.
Parse the given string as xml and return an XmlDoc object which can be queried or turned into JSON.
xml an xml formatted string to parsevar d = Xml.load("<hello>world</hello>");
Fetch a local or a remote file and parse as xml. Returns an XmlDoc object.
url is a local or remote path to an xml file// A remote file
var remote = Xml.loadFrom("http://somewhere/over/the/rainbow.xml");
// A local file
var local = Xml.loadFrom("c:\\somewhere\over\the\rainbow.xml");
An XmlDoc is an object that wraps an xml document and which has a few functions for querying the underlying document.
Execute an XPath query and return the results. The result is a list of objects, each object represents the matching xml node.
xpath a well-formed XPath expressionvar doc = Xml.load("<hello>world</hello>");
var allHellos = doc.xpath("//hello");
Returns a JSON/JavaScript version of the document which can then be inspected in the flow.
var doc = Xml.load("<hello>world</hello>");
var docObject = doc.json();
The Http module enables http requests to be sent within a flow.
Send a HTTP GET request. Returns a reply object containing;
status the http status-codedata a string containing the data receivedheaders an object containing the headers receivedurl the url to GETopts options, an object which may contain the following properties:
credentials (optional) for basic-auth - an object containing;
user username for the http resourcepass password for the http resourceheaders (optional) an object defining additional headers to include in the requestuseragent (optional) a string overriding the default useragenttimeout (optional, default 60000) how many ms to wait for the request to completecontenttype (optional) the contenttype of the request// Anonymous
var reply = Http.get("http://somewhere/over/the/rainbow.txt", {});
if (reply.status == 200) { // Status: OK
...
}
// With basic-auth user/pass
Http.get("http://somewhere/over/the/rainbow.txt", { 'credentials': {'username': 'John', 'password': 'ramb0' } });
Send a HTTP POST request. Returns a reply object containing;
status the http status-codedata a string containing the data receivedurl the url to POST todata a string to POSTopts options, an object containing additation options for the request (see description in Http.get)// Anonymous
var reply = Http.post("http://somewhere/over/the/rainbow.txt", "data=123", {});
if (reply.status == 200) { // Status: OK
...
}
Send a HTTP PUT request. Returns a reply object containing;
status the http status-codedata a string containing the data receivedurl the url to PUT todata a string to PUTopts options, an object containing additation options for the request (see description in Http.get)// Anonymous
var reply = Http.put("http://somewhere/over/the/rainbow.txt", "data=123" {});
if (reply.status == 200) { // Status: OK
...
}
Send a HTTP DELETE request. Returns a reply object containing;
status the http status-codedata a string containing the data receivedurl the url to DELETEopts options, an object containing additation options for the request (see description in Http.get)// Anonymous
var reply = Http.delete("http://somewhere/over/the/rainbow.txt", {});
if (reply.status == 200) { // Status: OK
...
}
The Ftp module enables reading and writing files on ftp servers.
Read a file.
url the url to the file to readopts options, an object which may contain the following properties:
user username for the ftp server, blank if anonymous access is allowedpass password for the ftp server// Anonymous
var data = Ftp.read("ftp://somewhere/over/the/rainbow.txt", {});
// With user/pass
var data = Ftp.read("ftp://somewhere/over/the/rainbow.txt", { 'user': 'John', 'pass': 'ramb0' });
Write a file to a remote ftp server.
url the url to the file to writedata the content of the fileopts options, an object which may contain the following properties:
user username for the ftp server, blank if anonymous access is allowedpass password for the ftp serverFtp.write("ftp://somewhere/over/the/rainbow.txt", "red, green, blue", {});
The Db module has functionality for connecting to databases. It currently supports sqlite, mssql and msaccess databases.
The connect method initialises a connection to a given database and returns a Database object.
type the type of the database, currently this should be “mssql”, “sqlite” or “msaccess”.connection the connection-string which contains information about how to connect to the database in questionvar db = Db.connect('sqlite', 'Data Source=C:\\MyFolder\\Test.db;Version=3;');
The database object returned from a Db.connect(...) invocation represents a database connection. It has two primary methods for interacting with a database; query and exec.
The exec method will execute a non-query (e.g. INSERT, UPDATE) and return the number of affected rows.
var affectedRows = db.exec('CREATE TABLE Test (id int, name string)');
The query method is used for queries (e.g. SELECT etc) and returns an array of objects representing the result of the query.
var rows = db.query('SELECT id, name from Test');
for (var i=0; i<rows.length; i++) {
Debug.showDialog("id="+row.id+", name="+row.name);
}
The begin() method is used to initiate a transaction.
var tx = db.begin();
A transaction object is conceptually similar to the database object. It has the same query and exec methods, but will delay the execution of the query or command until commit() is invoked and of course maintains transactional integrity. If the rollback() method is invoked the query and exec operations already made are discarded.
A commit() invocation will commit the tx to the db.
tx.exec("INSERT INTO Test (id, name) VALUES (1, 'John')");
tx.exec("INSERT INTO Test (id, name) VALUES (2, 'Jane')");
// Commit John and Jane
tx.commit();
A rollback() invocation will rollback the tx.
tx.exec("INSERT INTO Test (id, name) VALUES (1, 'John')");
tx.exec("INSERT INTO Test (id, name) VALUES (2, 'Jane')");
// John and Jane are not needed anyways
tx.rollback();
The database object returned from a Db.connect(...) invocation represents a database connection. It has two primary methods for interacting with a database; query and exec.
The exec method will execute a non-query (e.g. INSERT, UPDATE) and return the number of affected rows.
var affectedRows = db.exec('CREATE TABLE Test (id int, name string)');
The Csv module can be used for parsing, manipulating and generating comma-separated files.
The parse method takes a csv formatted string and returns an array of objects or arrays - one for each row in the string. There is also a parseFile variant which is identical to the parse method except that it takes a filename as its first argument.
content the csv stringoptions provides the options for the parserThe options object can have the following fields:
delimeters a list strings used to separate the columns of the content - default is [',',';']header can be set to
true to indicate that a header is present in the first line of the content or you can set it to annull (the default) which will cause the parsed result to be an array of arrays instead of an array of objectsquotedFields which will strip quotes from the data (if present in the content) - default falsevar csv = Csv.parse('foo;bar\n100;200', {header: true})
The csv variable will now contain:
[
{ foo: 100, bar: 200 }
]
or if there is no header:
var csv = Csv.parse('100;200\n300;400', {})
The csv variable will now contain:
[
[ 100, 200 ],
[ 300, 400 ]
]
The stringify(arr, quoteStrings, delim) method will take an array of objects or an array of arrays generate a csv string.
arr the array to convert to a csv stringquoteStrings a boolean value indicating whether to add quotes to strings or not (default false)delim the delimeter string to separate fields (default ',')var arr1 = [['foo','bar'],[1,2]];
var arr2 = [{foo: 3, bar: 4}];
var csvStr1 = Csv.stringify(arr1);
var csvStr2 = Csv.stringify(arr2);
csvStr1 and csvStr2 will now both have the value foo,bar\n1,2.
Load and parse and Excel spreadsheet. It can either return the entire spreadsheet or a selected range of cells. If the header option is set then the returned value will be be a map/object with the column names as keys - otherwise an array is used. If index is set then then values in the index column will be used as keys - otherwise an array is used. If both are set then both dimensions will use values as keys. See the examples below.
file path for an Excel spreadsheet to loadoptions options for parsing the spreadsheet - use {} to return the entire spreadsheet
table define a table to returnrange which range does the table reside in e.g. 'A1:D20'header is a boolean to determine if the top row of the header is a tableindex is a boolean to determine if the initial column is an index columnworksheet is the name of the sheet to load data fromGiven the following simple spreadsheet in the worksheet named ‘Sheet1’:
| cell 1 | cell 2 |
| cell 3 | cell 4 |
The following code will load the spreadsheet and pick out the value stored at cell1.
var table = Excel.load('myspreadsheet.xlsx', {});
var cell1 = table["Sheet1"][0][0];
Given the table below, situated in worksheet “Sheet1” at A1:B3:
| header 1 | header 2 |
|---|---|
| cell 1 | cell 2 |
| cell 3 | cell 4 |
Use the following code to pick out cell4.
var table = Excel.load('myspreadsheet.xlsx', { table: { range: 'A1:B3', worksheet: 'Sheet1', header: true } });
var cell4 = table[2]['header 2']; // 3rd row (0 is first row), column with header 'header 2'
Given the table below, situated in worksheet “Sheet1” at A1:B3:
| header 1 | header 2 | |
|---|---|---|
| I1 | cell 1 | cell 2 |
| I2 | cell 3 | cell 4 |
Use the following code to pick out cell2.
var table = Excel.load('myspreadsheet.xlsx', { table: { range: 'A1:C4', worksheet: 'Sheet1', header: true, index: true } });
var cell2 = table['I1']['header 2'];
Removes a single sheet from the workbook.
filename the path to the excel file to be updatedsheet the name of the sheet to deleteExcel.deleteSheet('data.xlsx', 'Sheet1');
Update the value stored in a single cell in a spreadsheet.
filename the path to the excel file to be updated - if the file does not exist a new one will be createdsheet the name of the sheet to updateaddress an “address” to a cell, e.g. “A1”value the value to write into the cell// write 1000 into A3 of Sheet1 in data.xlsx
Excel.updateCell('data.xlsx', 'Sheet1', 'A3', 1000);
Update values stored in a spreadsheet. This method is a lot more performant than the single cell version if you need to store multiple values.
filename the path to the excel file to be updated - if the file does not exist a new one will be createdsheet the name of the sheet to updateaddress an “address” of the starting cellvalues the valued to write into the cells - this should be a 2 dimensional array (like a table)// The data to write
var data = [
[10, 20, 30],
[40, 50, 60]
];
// write data into data.xlsx, Sheet1 starting at A1
Excel.updateCells('data.xlsx', 'Sheet1', 'A1', data);
This will result in a table that looks like:
| A | B | C | |
|---|---|---|---|
| 1 | 10 | 20 | 30 |
| 2 | 40 | 50 | 60 |
The Settings object contains values that can be read/written to affect the behaviour of a flow. The following properties are available:
CommandRetries (int - read+write) defines the number of times a command is retried before it is considered to fail. Default is 3.CommandRetryDelays (Array[100, 200, 400, 800, 1600]. When the number of retries exceed the given delays the last value in this array is used for all overflowing retries.Settings.CommandRetryDelays = [100, 100, 100];
var retries = Settings.CommandRetries;
Debug.showDialog("Retries: " + retries);
Inserts a warning in the log.
key the key of the message - keep this as a constanttext the text to insertLog.warn('greeting','hello there');
Inserts a informational line in the log.
key the key of the message - keep this as a constanttext the text to insertLog.info('greeting','hello there');
Controls the log verbosity of the application driver.
level the new log level. Must be one of the following: none, fatal, error, warn, info, debug.options optional additional options
useStdOut (defaults to false) boolean value indicating if instrumentation log should go to the application stdout or to manatee log.Log.setDriverLogging('info', { useStdOut: true });
The Window module has functionality for dealing primarily with the main window of an application. In contrast the Windows module supports interacting with all the windows on the desktop.
Get the title of the main window.
var title = Window.title();
Minimize the main window.
Window.minimize();
Check if the main window is minimized.
if(Window.isMinimized()) {
...
}
Maximize the main window.
Window.maximize();
Check if the main window is maximized.
if(Window.isMaximized()) {
...
}
Put focus on the main window.
options optional object with options for focus. Supported options:
useCachedUI boolean indicating if UI component lookup should use the UI itself or the underlying model. Defaults to false (underlying model traversal).Window.focus();
Send keyboard events (simulated typing) to a window. Supports special strings for sending special keys.
keys the keys to send - this is a stringoptions optional object with options for sendkeys, supported options:
focus [bool] whether to focus the window prior to sending the keysWindow.sendKeys("foo bar");
// or to focus the window prior to sending the keys
Window.sendKeys("foo bar", { focus: true });
Restore the main window to a previous state and location.
Window.restore();
Get whether or not a modal (dialog) is shown.
var modalIsShown = Window.modalShown();
Get whether or not a window with the given title is shown.
var windowIsShown = Window.withTitleShown("My Window");
Dims the window owned by the flow.
level the amount of dimming, 0-255. 255 is opaque and 0 is transparent.Window.dim(100)
The Windows module has functionality to inspect and manipulate the Windows of the desktop.
The all() method will return an array of window proxy objects representing all windows on the desktop.
var allWindows = Windows.all();
The forApp() method returns an array of window proxy objects representing all the windows of the application.
var applicationWindows = Windows.forApp();
The primary property returns a single window proxy object representing the primary or main window of the application.
var pw = Windows.primary;
The window proxy object returned by the Windows module methods represents a desktop window and can be manipulated with the following methods and properties.
Move the window to the given x,y coordinates.
var pw = Windows.primary;
// Move the window to (100,100) from the topmost left corner of the screen.
pw.move(100, 100);
Resize the window to the given dimensions.
var pw = Windows.primary;
pw.resize(100, 100);
Make the window the focused (topmost) window.
var pw = Windows.primary;
pw.focus();
Maximize the window.
var pw = Windows.primary;
pw.maximize();
Minimize the window.
var pw = Windows.primary;
pw.minimize();
Restore the original state of the window (after having maximized or minimized it).
var pw = Windows.primary;
pw.restore();
Grab a screenshot of the window. The screenshot will be returned as a base64 encoded string.
var pw = Windows.primary;
// img is a base64 encoded string
var img = pw.screenshot();
Send keyboard strokes to the window.
var pw = Windows.primary;
pw.sendKeys("abc");
Get the title of the window.
var pw = Windows.primary;
var t = pw.title;
Get the class of the window.
var pw = Windows.primary;
var t = pw.class;
Get/set whether this window is considered the primary for the application.
var ws = Windows.forApp();
if (!ws[0].isPrimary) {
ws[0].isPrimary = true;
}
Get a boolean value indicating whether or not the window is maximized.
var ws = Windows.forApp();
if (!ws[0].isMaximized) {
// do something then
}
Get a boolean value indicating whether or not the window is minimized.
var ws = Windows.forApp();
if (!ws[0].isMinimized) {
// do something then
}
Get/set the bounds (location and size) of the window.
var pw = Windows.primary;
var bounds = pw.bounds;
// Move 10px left and down
bounds.x = bounds.x + 10;
bounds.y = bounds.y + 10;
// Decrease width and height with 10px
bounds.width = bounds.width - 10;
bounds.height = bounds.height - 10;
// Update the window bounds with the new values
pw.bounds = bounds;
The Processes module similarly to the windows module is used to enumerate and manipulate processes running on the local machine.
The all() methods enumerates all processes on the local machine. It returns an array of process proxy objects.
var ps = Processes.all();
for (var i=0; i<ps.length; i++) {
// then do something with each process proxy
}
Get the current process for the application (for which the flow is defined).
var p = Processes.current;
Debug.showDialog(p.name);
The spawn(...) method can be used to create new processes. It takes 3 arguments;
path to the executable to launcharguments for the executable (optional - default null)working directory (optional - default null)shell (boolean) whether to launch the process in a shell environment - this must be set to true for url-handlers to activate (optional - default false)It returns a process proxy object fronting the process spawned.
var p = Processes.spawn("C:\\Path\\To\Executable.exe");
Debug.showDialog(p.name);
Kills a process.
var p = Processes.all()[0];
p.kill();
The wait(...) method will wait for the given process to exit. It takes an integer, the maximum number of milliseconds to wait for the process as its argument. It returns a boolean indicating whether the processes exited (true) or the given timespan elapses (false).
// Wait max 1s for the first process to exit
if (Processes.all()[0].wait(1000)) {
// it exited
} else {
// 1s elapsed
}
Sending some input to a running process is achieved with the stdin(...) method.
This can normally only be done for processes spawned by yourself via the Processes.spawn(...)](#spawning-new-processes) method.
var p = Processes.spawn(...);
p.stdin("hello");
Reading from the output of a process is done via the stdout(...) method. It takes an int - the number of lines to read - and returns a task which completes with the lines read as an array of strings once the given number of lines has been read.
This can normally only be done for processes spawned by yourself via the Processes.spawn(...)](#spawning-new-processes) method.
var p = Processes.spawn(...);
var lines = null;
// Read 3 lines, then kill the process
p.stdout(3).then(function(threelines) {
lines = threelines;
p.kill();
});
p.wait(20000);
Debug.ger(lines);
It is also possible to read from standard-error output - simply use the stderr(...) method instead of stdout(...).
Get the id of the process.
var pid = Processes.current.id;
Get the name of the process.
var pname = Processes.current.name;
Get the path of the executable for the process.
var path = Processes.current.path;
Get the working directory of the executable for the process.
var pwd = Processes.current.wd;
Get the virtual or private memory (integers) usage of the process.
var virtualMem = Processes.current.vmem;
var privateMem = Processes.current.pmem;
Gets a boolean indicating whether the process has exited.
if (Processes.current.exited) {
// whoops
}
Gets the number of milliseconds elapsed since the process was spawned (as longs as it has not exited).
var uptime = Processes.current.uptime;
Show some text in a debug dialog. Essentially the same as Dialog.info("Debug", text).
text the text to displayDebug.showDialog("hello there");
The Debug.ger() method pauses the running flow (as any other dialog) and shows a debugger dialog which includes an inspector and a REPL (read-eval-print loop).
The inspector window lets you inspect the global values in the flow as well as the argument given. The variables are displayed in a tree which can be expanded to reveal the structure of the objects.
The debugger shown above was shown with the following code:
var x = { foo:'bar', baz: 123 };
Debug.ger(x);
Expanding the CURRENT node will give you:
You can also explore the global variables (those defined in the outermost) scope of a flow. Here we show a field.
The REPL tab of the Debug.ger can be used to try running small snippets of code in the context of the current flow. You can do anything via the REPL that you can do in a flow.
Clicking the “Run” button will run the code written and display the time it took to run as well as the result.
This method can also be used as Debug.attach() and Debug.inspect() but some of us prefer the simplicity and raw hipster essence of Debug.ger().
The Fs module is used to interact with the filesystem of the local machine.
The tmpfolder property holds the path to the temp folder.
var folder = Fs.tmpfolder;
Returns a list of files found in the directory given by the path argument. The path may contain wildcards * in its last segment.
A second option argument can be passed, which can have the boolean property deepMatch. When this property is set to true, files matching the filename given in the path argument in any sub-folder will be returned.
Default behavior is to do a shallow file listing.
var files = Fs.ls('c:\\somedir\\somefile*.txt');
// Get all .txt files prefixed with somefile in somedir
var files = Fs.ls('c:\\somedir\\*.txt', { deepMatch: true });
// Get all .txt files in any sub directory under C:\somedir - at any depth
Read the contents of a file with the read(...) function.
var html = Fs.read('c:\\somedir\\somefile.html');
Writes arbitrary text to an arbitrary text file. If the file exists, it will be overwritten. If the file doesn’t exist, it will be created with the given contents. The contents are written using UTF-8 encoding without a byte order mark (BOM).
Throws appropriate exceptions if the write fails.
Fs.write('c:\\somedir\\somefile.html', '<html><body><h1>Generated html!</h1></body></html>');
The tmpfile function will generate a random, non-conflicting filename in the temp folder.
var tmpFilePath = Fs.tmpfile();
The App variable contains functions relating to the app itself.
Returns the current location (if applicable for the given application type – non-webapps do not support this).
var loc = App.location();
Navigates to the given url. If the url is relative (e.g. somefolder/somefile.html) it will get appended to the current url.
url a string representing the destination for the navigation act// Absolute url
App.navigate("http://dr.dk");
// Relative url
App.navigate("news");
Store a value in the current session storage. This will be available across flows and for all applications.
key a string denoting the key to store the value undervalue an object to storeoptions an optional options object. Supported options are;
expires a timeout in minutes - after this interval has passed the value will be deleted. Default is 1440 min (= 1 day).// Storing a simple value - a string
App.session().write('mykey', 'myvalue');
// Storing an object - expires in 1 hour
App.session().write('myotherkey', { greeting: 'hello' }, { expires: 60 });
Read a value stored in the current session.
key a string denoting the key to retrieve the value forvar v = App.session().read('mykey'); // e.g. will return 'myvalue'
Delete a value.
key a string denoting the key to deleteThe value deleted.
var v = App.session().delete('mykey'); // e.g. will return 'myvalue'
Quits the application - be aware that this is a hard shutdown and the user will not be prompted to save any information before the application exits.
App.quit();
A sticky is a persistent window which can be configured to remain top-most as long as it’s shown. The user is able to interact with the items shown in the sticky e.g. clicking on links, opening pdf previews etc. Keyboard interaction is also supported, use:
| Key | Action |
|---|---|
↓ |
Focus next (down) item |
↑ |
Focus last (up) item |
.or - |
Toggle collapsed state of item |
<space> |
Run primary action (depends on the type of the item) |
<enter> |
Run secondary action |
<esc> |
Close sticky (or exit from search if search field is focused) |
| any char | Open search field |
Open a new sticky window with the given name and opts. The function can be called multiple times with the same name argument in order to update an already showing sticky.
name the name of the window to open, only one sticky-window can have this nameopts is an object containing the configuration for the sticky, it may have the following properties:
embed (boolean, default false) should the sticky be embedded in the window of its owner application? When embed is set to true some of the below options are not relevantresizable (boolean, default false) should it be possible to resize the sticky windowmovable (boolean, default false) should it be possible to move the sticky windowsearchable (boolean, default false) should the contents of the sticky be searchableshowFooter (boolean, default false) should a foother with a nice logo be shownfontSize (int, default 12) the base font size to use for items in the stickyfocusOnUpdate (boolean, default false) when the sticky is updated should we focus the sticky window again?topMost (boolean, default false) should the sticky be top-most alwaystitle the title of the sticky windowlocation determining where the sticky should be shown, contains:
type which type of position - currently only ‘absolute’ is allowedtop px from the top of the screenleft px from the left side of the screenwidth px width of stickyheight px wheight of stickyitems a list of sticky items to show in the window, each is defined by:
type which type of item - see belowWe support the following types of items.
The first is GIF which simply shows an (animated) gif - it may have the following properties:
source an url for a gif, can be remote or localAn ACTION will run the flow with the name given when the sticky is clicked. For the ACTION type the following are valid.
name the name of the action to launch - this should be uniqueheader and body if set these will be shown instead of action name on stickyheight the height of the item in pixelsinputs is an object containing the named inputs for the actionfocus whether or not the item should have focus (only the first item with this property set to true will be focused)Will show a pdf with an optional preview. The options are:
source an url (remote or local) to the pdf to showheader and body if set these will be shown instead of the sourcelinkText an optional text (or unicode icon) to show as a link to the source filelink an optional link to direct the user to (default is value of source)height the height of the preview pane in pixelscollapsible whether or not the preview should be collapsible (default false)collapsed the initial state of the preview (default false)saveable whether or not it should be possible to save the pdf (default true)printable whether or not it should be possible to print the pdf (default true)focus whether or not the item should have focus (only the first item with this property set to true will be focused)Will render a HTML snippet or a whole HTML page into an item. Should be used for render styled text, e.g. headers and such - not recommended for complete pages. Options are:
source html text or an url (remote or local) to the pdf to showheight the height of the itemfocus whether or not the item should have focus (only the first item with this property set to true will be focused)Will act as a link (e.g. to an internet resource or a local file).
link the link to activate (when clicked)text optional - the text to display (default is the url of the link)prefix optional - the text to display before the link textsuffix optional - the text to display after the link textfocus whether or not the item should have focus (only the first item with this property set to true will be focused)Sticky.open(
'mySticky',
{
embed: true,
location: {
type: 'absolute',
top: 100,
left: 100
},
items: [
{
type: 'GIF',
source: 'http://gifs.com/cat'
},
{
type: 'ACTION',
name: 'SomeOtherAction',
header: 'Some other action',
body: 'Click to run'
},
{
type: 'PDF',
source: 'http://pdfworld.com/arandompdf.pdf',
link: 'http://pdfworld.com/aboutarandompdf',
height: 100,
collapsible: true,
collapsed: false,
saveable: false,
focus: true
},
{
type: 'HTML',
source: '<h1>Big header</h1><h2>Smaller header</h2>',
height: 50
},
{
type: 'LINK',
link: 'http://sirenia.eu',
prefix: 'Go to ', text: 'Sirenia', suffix: ' now'
}
]
}
);
Get the model used to construct the sticky,
name the name of the sticky to retrieve the model for (must be opened prior…)var m = Sticky.model('mySticky');
// Perhaps do some changes to model m and then
// Sticky.open('mySticky', m);
// to update the stikcy with the changes made to its model
Close a named sticky.
name the name of the sticky to close (must be opened prior…)Sticky.close('mySticky');
Hide a named sticky.
name the name of the sticky to hide (must be opened prior…)Sticky.hide('mySticky');
Show a previously hidden sticky.
name the name of the sticky to show (must be hidden prior…)Sticky.show('mySticky');
The timer module provides a simple interface for timing parts of flows. It is especially useful in combination with our Analytics product allowing you to time crucial parts of your flows.
Start a named timer. If you invoke this method twice with the same name (argument) you’ll reset the timer every time.
name the name of the timer to startTimer.start('myTimer');
Log an event on a named timer. Useful only in combination with our Analytics product. The logged event will contain the name of the timer, the milliseconds since the timer was started and the given message.
name the name of the timer to log an event onmessage the message to logThe number of milliseconds since the timer was started.
Timer.log('myTimer', 'A message goes here');
Stop a named timer.
name the name of the timer to stoplog whether or not a message should be loggedThe number of milliseconds since the timer was started.
// Will log an event and stop 'myTimer'
Timer.stop('myTimer', true);
The notifications module makes it possible to display non-interactive notifications.
Shows a notification.
name the name of the notification, save this for future update invocationsheader the header text to showbody the body text to showoptions is an object with the following additional options:
severity the severity of the notification, choose between “INFO”, “WARN” and “ERROR”. Default is “INFO”.timeout seconds for the notification to show. Default is 30.callback a javascript function to execute when the user clicks the notification. Default null.embed defines whether the notification should be embedded in the current application or shown on the desktop (default is false = show on desktop)sound a string (one of asterisk, beep, exclamation, hand, question) which indicates a system sound to play once the notification is shown.Show an INFO notification for 30 seconds.
Notification.show('hello', 'Seasonal greetings!', 'Felice navidad', {});
Show a WARN for 5 seconds.
Notification.show('warn', 'Its complicated', 'Something broke down', { severity: 'WARN', timeout: 5 });
Notifications with callbacks.
function RaiseTheAlarm() {
Notification.show('Oh no!', 'You clicked the first notification', { severity: 'ERROR' });
}
// Callback to previously defined function
Notification.show('warn', 'Its complicated', 'Something broke down, click here', { severity: 'WARN', timeout: 5, callback: RaiseTheAlarm });
// Callback to anonymous function
Notification.show(
'warn',
'Its complicated',
'Something broke down, click here',
{
severity: 'WARN',
timeout: 5,
callback: function() {
Log.info('clicked', 'Notification was clicked');
}
});
Update the information in an already shown notification.
name the name of the notificationheader the header text to changebody the body text to changeoptions is same as for invoking showUpdate the notification named “hello”.
Notification.update('hello', 'Seasonal greetings anew!', 'Merry Christmas', {});
Close an open notification. Notifications will automatically be hidden but this can force that action.
name the name of the notificationClose the notification named “hello”.
Notification.close('hello');
The Tasks module can be used to paralellize parts of a flow. This is useful for e.g. doing concurrent http requests or running background tasks. It is not intended for use with field-operations i.e. interacting with a host applications UI since this interaction cannot be parallelized. Furthermore you should not display dialogs in parallelized tasks as they can block the calling flow.
Use the run method to start a new task.
fun a function to run in parallelTask object.Run some tasks and wait for the result.
var t = Task.run(
function() {
var i = 0;
while (i<1000) {
i = i + 1;
}
return i;
});
// Wait for t to complete or 1000ms to elapse
if (t.wait(1000)) {
// Access the result
if (t.done && !t.failed) {
Debug.showDialog("It completed with result="+t.result);
} else (t.failed) {
// only access t.error if t.failed == true
Debug.showDialog("Took too long or errored? "+t.error !== null);
}
} else {
// 1 sec elapsed without the task completing
}
Run a task and execute a function when the task is done.
Task.run(...).then(function(result){
// do something with the result of the task
});
This is used to wait until all the tasks given as arguments complete or given milliseconds elapse.
tasks - an [array of tasks or javascript functions] to run asynchronously (and then wait for)timeout [int] denoting the max number of milliseconds to wait for the tasks to completeA [bool] indicating wether or not all tasks completed.
var t = Task.run(function() { ... });
var tasks = [Task.run(function() { ... }), function() { ... }, t];
// Wait for tasks to complete or 1000ms to elapse
if (Task.waitAll(tasks, 1000)) {
Debug.showDialog("It completed!");
} else {
Debug.showDialog("Took too long");
}
This is used to wait until one of the tasks given as arguments completes or given milliseconds elapse.
tasks - an [array of tasks or javascript functions] to run asynchronously (and then wait for one of)timeout [int] denoting the max number of milliseconds to wait for any of the task to completeAn [int] denoting the index of the first task to complete or -1 if no tasks complete within given deadline.
var t = Task.run(function() { ... });
var tasks = [Task.run(function() { ... }), function() { ... }, t];
// Wait for tasks to complete or 1000ms to elapse
var idx = Task.waitAny(tasks, 1000);
if(idx > 0) {
Debug.showDialog("We have a winner: "+idx);
} else {
Debug.showDialog("Took too long. Everybody lost.");
}
A javascript representation of a .NET task. It has 2 methods; wait(milliseconds) which can be used to wait for the task to complete or the given milliseconds to elapse, whichever comes first and then(func) which can be used to run a function when the task completes.
For an example see the Run method on the Task module.
This very simple module provides utility functionality for dealing with globally unique identifiers - aka standardized random strings. Use these if you need to generate a unique file name or unique string in general.
Returns a new random standard globally unique identifier
var guid = Guid.get();
The tables module provides functionality to read and write information stored on Kwanza and accessible from the configuration interface (Cuesta). It is meant to provide an easy way to add mapping or other types of tabular data to a flow. The UI for managing tables are shown below.
Note that only UTF8 formatted csv files are supported.
Navigating the indvidual cells in the table can be done via the keyboard in a spreadsheet like manner. alt+<arrow-key> will move the focus depending on the arrow-key pressed. The video below shows an example of this (the keys pressed are shown in the bottom left corner of the video).
Inserting and deleting rows can also be done via the keyboard. Press ctrl+n to insert a row directly below the currently focused row.
Deleting a row is done via the ctrl+backspace key. It will remove the currently focused row.
This is done similarly to adding and removing rows but the cursor must be placed in the column header. ctrl+n adds a new column, while ctrl+backspace removes the current.
| Key | Action |
|---|---|
alt+↓ |
Focus cell below |
alt+↑ |
Focus cell above |
alt→ |
Focus cell right |
alt+← |
Focus cell left |
ctrl+shift+a |
Insert new row/column |
ctrl+shift+backspace |
Remove row/column |
The .map function will parse a table as a map, meaning that it will use a given column as an index. This is mainly useful if there is a column with unique values to use for the index. The returned structure will be a map with the column headers as keys.
Given the table named foo:
| A | B |
|---|---|
| idx1 | val1 |
| idx2 | val2 |
And the code:
var m = Table.map('foo', 'A');
You’ll get the following object back:
{
'idx1': { 'A': 'idx1', 'B': 'val1' },
'idx2': { 'A': 'idx2', 'B': 'val2' }
}
Which can then be used in the following manner:
var idx2val = m['idx2']['B'];
// or if the column names are valid javascript identifiers
var idx1val = m.idx1.B;
name - [string] the name of the table to create a map fromindex - [string] the name of the column to use as an indexThe .rows function will return the raw table as a javascript array of arrays.
Given the table named foo identical to the table from .map and the code:
var m = Table.rows('foo');
You’ll get the following object back:
{
rows: [
['idx1', 'val1'],
['idx2', 'val2'],
]
}
Which can then be used in the following manner:
var idx2val = m.rows[1][1];
name - [string] the name of the table to create fromThe object returned from both .map and .rows contains a .save function which can be used to write data back to a table.
Given the table from the previous examples and the code:
var m = Table.rows('foo');
m.rows[0][1] = 'newval1';
m.save();
Will change the value of the specified cell and update the table. This also works if .map is used:
var m = Table.map('foo', 'A');
m.idx1.A = 'newval1';
m.save();
Adding to a table read by the rows approach:
var m = Table.rows('foo');
m.rows.push(['idx3', 'val3']);
m.save();
This will add a new row with idx3 and val3. When using rows the order of the input elements matter and should match the order of the columns.
The same information can be added when the table is read via the map approach as follows:
var m = Table.map('foo', 'A');
m.rows['idx3'] = { 'A': 'idx3', 'B': 'val3'};
m.save();
Removing a row from a table read by the rows approach is done by removing the corresponding array entry:
var rowToDelete = 0;
var foo = Table.rows("foo");
foo.rows.splice(rowToDelete, 1); // Delete the row w index 0
foo.save();
and the equivalent delete of a entry from a map table:
foo = Table.map('foo', 'A');
delete foo["idx1"]; // Delete the entry with key 'idx1'
foo.save();
This is achieved by calling the selectFrom method on the structure created by the .map function. The selectFrom function takes either a format string or an object with options to generate the content for a typeahead.
var m = Table.map(...);
m.selectFrom('{{someColumn}} some text {{someOtherColumn}}');
Using a format string (above) and an object with options (below).
var m = Table.map(...);
m.selectFrom({
format: '{{someColumn}} some text {{someOtherColumn}}',
minInputLength: 3,
filterMode: 'contains'
});
The env module provides some contextual information for flows.
Get the username for the current user.
var u = Env.userName;
Get the name of the machine.
var m = Env.machineName;
Get the domain for the current user.
var u = Env.userDomain;
Get information about the primary screen of the local machine.
var s = Env.primaryScreen;
s will now be an object like so:
// s
{
width: 1024,
height: 768,
primary: true
}
Get information about all the screens attached to the local machine.
var screens = Env.screens;
screens will now be an array of screen objects, like so:
// screens
[
{
width: 1024,
height: 768,
primary: true
},{
width: 1280,
height: 1024,
primary: false
}
]