This guide covers the information required to develop viabl.ai build tools. Each build tool is stored as a JavaScript file in the libraries/wizards folder under the main viabl.ai platform install. Along with the JavaScript file there should be a matching .png which holds the 24x24 icon for the tool.
The concept of a build tool (in the viabl.ai platform) is a logical process which presents some UI to the user and (optionally) creates objects or modifies existing objects. This is achieved by presenting individual pages to the user which contain any combination of supported input & display widgets. The tool developer has complete control of inter-page functionality (including but not restricted to specifying which page is next) along with any final actions when the tool is complete and/or the edit operation has been accepted. As the user progresses through the pages, the underlying data payload is updated to allow the tool to access all the currently captured inputs. Tools can be initiated in either create mode or edit mode.
A build tool definition file is split into 2 sections. The top of the file contains a meta definition of the tool (as JS comments). The remainder for the file is a JSON object which describes both the layout and the functionality of the tool. This JSON object is wrapped in a single wizzards.register call.
n.b. A build tool can have supplimental files (which should also be held in the wizards folder). An example of this are the LLM design-time build tools which depend upon an additional server-side gptBuild.php script (integrated via a $.ajax in the individual tools)
The meta definition is represented as JavaScript comment lines at the top of the definition file. An example definition can be seen below...
// @type: wizzard
// @title: Add LLM Decision Tree
// @description: Add an LLM Decision Tree
// @group: LLM Integration
// @contexts: ["explorer"]
// @catalog_style: true
// @style: background-color: #abeabc; border-style: solid; border-color: #34a853; border-width: medium; color: #000000;
The purpose of the definition allows the server-side wizzards.php script to build a comprehensive (an possibly filtered) list of build tools when are returned to the browser at viabl.ai startup. Each property should be on it's own line and the format is...
// @<property name>: <property value>
Property Name | Description |
---|---|
type | This property must be "wizzard" |
title | The name of the tool (as displayed in the Build Tools panel) |
description | The HTML displayed in the title of the tool dialog |
edit_description | The HTML displayed in the title of the tool dialog when in edit mode. If not supplied, the description property is used. An additional feature in the edit_description is what if the tool is associated with a viabl.ai object, {{name}} can be supplied which is replaced by the name of the object being edited (see xrSuperQuestion for an example) |
menu_description | The name displayed when the build tool is included on a popup menu (e.g. if the "treebuild" context is specified, the tool will be visible on the tree popup menu with this text) |
submenu | When included on a menu (e.g. tree popup menu) this text specifies a sub-menu name to include the tool under. An example can be seen in the xrDialog tool |
importance | This is a number which defines the order of the tools when included on a menu (e.g. tree popup menu). Any range of numbers can be used. An example can be seen by comparing the xrExistingObject and xrSuperQuestion tools |
group | The name of the group which contains the tool in the Build Tools panel. These group names are scanned at startup to build a list of unique group names (to to add a new build tool group, just supply a new name) |
contexts | This is a list of strings which specify where this build tool is available. The full list of contexts is listed in it's own section below |
deployments | Specifies which deployment mode(s) are applicable for this tool. Possible values are "chat", "silent" and "interactive". For example, if "interactive" is omitted then a Knowledge-Base defined as being ONLY "Dialog Deployment" will not have this tool available |
catalog_style | A boolean value which specifies whether objects created by the tool are displayed using the tool's style (as specified by the style property below). This property is usually set to "true" |
style | The CSS string applied to the wrapper DIV containing the tool on the Build Tools panel. e.g. for the xrSuperQuestion, the style is... background-color: #8ab2f4; border-style: solid; border-color: #4285f4; border-width: medium; color: #000000; |
dual_mode | If true then this build tool is passed (at startup) an existing object (if available). This functionality is used in the xrSuperKnowledge tool as the "Add Knowledge" can either create a new knowledge object (e.g. Decision Tree) or add knowledge to an existing question. The actual implementation of the dual modes (operate as a new or modify and existing) is handled by the tool developer |
superincludes | If specified, this build tool will only be available if the current Knowledge-Base was created by one of the listed super wizzards. For example see the risk_aggregation and rick_indicator tool |
super | If true then this is a super wizzard. Super wizzards start operating when a new Knowledge-Base is created based on one this tool. An example is the risk_super wizzard. There will be a separate section (in this document) to describe this functionality |
parent_wizzard | If supplied, this is the name of an existing build to use as the basis for the tool operation. An example of this is the crmHubSpot build tool which supplied additional configuration options which are picked up and acted on by the parent samsAPI tool |
The "contexts" property in the meta definition describes where the build tool is available in the platform. The property value contains zero to many individual context strings. Below are all the possible values...
Context Name | Platform Location / Action |
---|---|
tree | [Draggable onto] a decision tree |
cases | [Draggable onto] a Decision or Lookup Table |
flow | [Draggable onto] a Dynamic or Troubleshoot Sequence |
explorer | Object Catalog popup menu |
map | Decision Map popup menu |
treebuild | Decision Tree (node) popup menu |
casesbuild | Decision Table (Add Column) popup menu and the Decision Rules "Add Object to Palette" panel |
hierbuild | Hierarchy Object editor popup menu |
flowbuild | Dynamic & Troubleshoot Sequence bottom popup menu |
procbuild | The "Available Actions" panel on the Procedure Object editor |
dlgbuild | The "Add Object" panel on the Dialog editor |
dmbuild | Decision Mining Tree (node) popup menu (>= V5.2 only) |
category | Object Catalog category (right-click cat name) popup menu |
project | Knowledge-Base (top left) dropdown menu |
treetoolbar | Buttons in the decision tree editor toolbar (see the additional "treetoolbar" section for some tips on this context) |
dmtreetoolbar | > 5.3.1 : Buttons in the decision mining tree editor toolbar (again see the additional "treetoolbar" section) |
maintoolbar | Buttons in the top purple area left of the search box |
Although build tools are primarily integrated into the viabl.ai platform via the supported contexts (see above), they can also be directly integrated at other locations by modifying the actual platform. A good example of this is the rename build tool which is included into the actual platform code at various locations (not supported by the meta context). If the platform consumes a build tool in this way, the following code shows an example integration
// "renameObj" is the catalog object to rename
let wizIdx = wizzards.findWizardByName("rename");
if (wizIdx >= 0) {
wizzards.start({
autoSelectedWizardIdx: wizIdx,
aObject: reanmeObj,
completeCB: function() {
// rename complete, possibly refresh a disply element
}
});
}
The main JSON object in the build tool contains both the definition and JavaScript code required to implement the functionality. The object is passed to the wizzards.register method. e.g.
wizzards.register({
<Build tool definition object>
});
The definition object has a number of properties and methods. The top level properties are...
property name | required | type | property value |
---|---|---|---|
size | no | object | Details of the size of the tool editor dialog |
help | no | string or object | URL of the page to display in response to the tool's "help" button |
getTitle | no | function | Function which returns the HTML title of the build tool dialog |
menu_description | no | function | Function which returns the text of the tool when included on a popup menu |
populate | no | object | Object containing functions which give full control over the availability of the tool in various contexts |
start_page | yes | string or function | The name of the initial page displayed to the user |
pages | yes | object | Object describing the contents of all the individual pages of the tool |
next | yes | function | Function which is used to both pre-populate individual pages, handle the page "Next" or "Done" processing and detain the next page to display |
update | no | function | Function called in response to various input elements being changed |
rendered | no | function | Function called once a page has been rendered to the DOM |
done | yes | function | Called when the tool (in create mode) has completed |
edit | no | function | Called when the tool is started in edit mode. The function encapsulates both the pre and post functionality |
This document will now give details of each property
The optional size property is an object containing the width & height (in pixels) of the tool edit dialog. e.g.
{
width: 700,
height: 700
}
The optional help property can be 1 of 3 values
help: "https://help.viabl.ai/help_page"
help: {
"new": "https://help.viabl.ai/create_help",
"edit": "https://help.viabl.ai/edit_help"
}
The optional getTitle property holds a function which returns the HTML title of the tool dialog title (when in both new and edit modes). If omitted either the description or the edit_description meta property is used.
getTitle: function(context, wizards, editingCatalogObject) {
switch (context.mode) {
case "new":
return "Creation mode";
case "edit":
return "Editing now";
}
}
The context object represents information about where the tool is begin initiated from (see separate section for more details). The wizards object gives access to the build tool framework with it's associated helper methods & settings (see separate section for more details). The optional editingCatalogObject is a reference to the catalog object being edited (will be null when in new mode).
The optional menu_description property holds a function which returns the text of the item used to indicate this build tool when included on a popup menu.
menu_description: function(editingCatalogObject, location) {
switch (location) {
case "casescolumn":
return "Add Knowledge to " + editingCatalogObject.aName;
}
}
The optional editingCatalogObject is the actual catalog the menu is associated with (if applicable). The optional location string specifies which particular popup menu is being shown (at present, this is just "tree", "cases" or "casescolumn").
The optional hideTool propercy can hold a function which should return either true of false. If the function returns true, the tool is completely removed from the platform for the duration of the active editor session.
hideTool: function() {
return true; // perminantly hide this tool
}
The optional populate property can hold an object (containing functions) which give full control over the tool visibility. At present the only supported method is the allow method...
populate : {
allow: function(location, catalogObject, editorParentObject) {
switch (location) {
case "category":
return catalogObject ? true : false; // Do not show in the "Base Classes" Object Catalog category
default:
return true;
}
}
}
The location parameter is a string representing the inclusion area. See the Build Tool Contexts section of this document for a complete list of possible values. If the location is related to a Catalog Object (e.g. Catalog popup menu) this parameter holds the object (otherwise it is null).
(> V5.2 only) The optional editorParentObject can contain a reference to the parent object of the catalogObject which the menu is being populated for. e.g. Right-clicking a node on a decision tree will result in the decision tree object being passed in the editorParentObject parameter, where-as right-clicking a node on the catalog will have a null editorParentObject.
The required start_page property is either a string (or a function which returns a string) providing the name of the start page. The pages for a build tool are held in the pages property (see separate section).
start_page: "initial_setup_page"
start_page: function(context, wizards, data) {
// Useful context properties are (context.targetObject, context.location)
return "supplemental_setup_page";
}
The context object represents information about where the tool is begin initiated from (see separate section for more details). The wizards object gives access to the build tool framework with it's associated helper methods & settings (see separate section for more details). The data object is the underlying data storage for this tool's create/edit session. The start_page function can use this opportunity pre-populate the data payload (if required).
The required pages property is an array of objects (each object representing an individual page). An example of the top level of this property might look like...
pages: [
{
name: "initial_setup_page",
elements: [
<objects describing the widgets on this page>
]
},
{
name: "confirmation_page",
elements: [
<objects describing the widgets on this page>
]
}
]
As can be seen, each page has a unique name (used primarily for the start_page and the next operations) and an array of elements. Each element represents a widget on this page. Widgets are stacked vertically and can either provide input functionality or used to display information (e.g. page title, error messages etc). The build tool framework provides an extensive collection of widgets. The complete list is included in the Build Tool Widgets section of this document. When modifying page element definitions, the passed 2nd wizards parameter gives access to various methods, there are detailed in their own section.
The next method is where the build tool performs (via JavaScipt code) the following actions...
The function declaration of the method is
next: function(currentPageName, wizards, data, isPopulating, context, completeCB) {
// your code goes here
}
As mentioned above, this function performs a number of actions. Each of these is listed individually bewlow
The function should specify the name of the "next" page to display by calling the passed completeCB function. This is done asyncronously (by calling the completeCB when ready) to allow (for example) $.ajax calls to be made to pre-populate the next page data. There are some reserved pseudo-names which perform specific action in the framework. "DONE" tells that framework that this is hte last page in this tool run. "ERROR" tells the framework that an error has occured and should not progress. "SINGLE_PAGE" represents a single page tool (which shows fewer buttons at the bottom of the dialog).
Simple 2 Page Tool Example
next: function(currentPageName, wizards, data, isPopulating, context, completeCB) {
switch (currentPageName) {
case "welcome_page":
completeCB("main_page");
break;
case "main_page":
completeCB("DONE");
break;
}
}
If the 4th isPopulating parameter is true, the function is being called before the page is rendered. The tool can modify the element definitions of the upcomming page and/or set properties in the data payload object. Note, the page is actually displayed when the completeCB function is called AND NOT WHEN THE FUNCTION ENDS!
Simple 2 Page Tool with Pre-Population Example
next: function(currentPageName, wizards, data, isPopulating, context, completeCB) {
switch (currentPageName) {
case "welcome_page":
if (isPopulating) {
// there is a "text" element on the "welcome_page" page with a name of "object_name". Default it via this code
data.object_name = "My Sample Object";
}
completeCB("main_page");
break;
case "main_page":
if (isPopulating) {
// there is a "checkbox" element on the previous "welcome_page" page with a name of "expert_mode". Is true then show the extra "extra_info" element on this "main_page", otherwise hide it
if (data.expert_mode) {
wizards.showElement("extra_info");
} else {
wizards.hideElement("extra_info");
}
}
completeCB("DONE");
break;
}
}
More sample code to Populate a dropdown with a custom list of Catalog Objects
next: function(currentPageName, wizards, data, isPopulating, context, completeCB) {
switch (currentPageName) {
case "welcome_page":
if (isPopulating) {
// there is a "dropdown" element on the "welcome_page" page with a name of "main_question". Fill it with catalog objects
let dd = wizards.findElementByName("main_question"); // find the definition of the element
dd.values = []; // empty the values
for (let c = 0; c < dictionary.aDictionary.length; c++) {
let o = dictionary.aDictionary[c];
switch (o.aType){
case TYPE_TEXT:
// add non-baseclass objects of type TEXT which do not have knowledge attached
if (o.flatProps.pid && !o.aTree && !o.aExamples && !o.aFlow) {
dd.values.push({
name: o.aID,
prompt: o.aName,
extra: o.GetDescription(false)
});
}
break;
}
}
}
completeCB("main_page");
break;
case "main_page":
...
}
If the 4th isPopulating parameter is false, the function is being called in response to the user either clicking "next" or "ok". The tool recieves the data payload object populated with the inputs on the current page (along with any data captured previously). Is the tool code determines invalid data, an error should be presented to the user and "ERROR" returned via the completeCB otherwise return the name of the next page (or "DONE")
Simple 2 Page Tool with Validation Example
next: function(currentPageName, wizards, data, isPopulating, context, completeCB) {
switch (currentPageName) {
case "welcome_page":
// no pre-populate or validation in this example
completeCB("main_page");
break;
case "main_page":
if (!isPopulating) {
// Only valid if extra_info is greater than 5 charaters in length
if (data.extra_info.length < 6) {
wizards.setElementProp("extra_info_error", "prompt", "Must be 6 or more characters");
wizards.showElement("extra_info_error");
completeCB("ERROR");
return; // Important, return here so we don't call the default "DONE" later
} else {
wizards.hideElement("extra_info_error");
}
}
completeCB("DONE");
break;
}
}
The optional update property contains a function which gets called when various input elements (on the currently displayed page) change. The Build Tool Element Types which trigger this event are "object", "checkbox", "list" and "dropdown"
update: function (pageName, wizards, data, elementDef, context) {
if (elementDef && elementDef.name == "num_vals") {
// the num_vals "dropdown" input has been changed
if (data.num_vals == "1") {
wizards.hideElement("extra_vals");
} else {
wizards.showElement("extra_vals");
}
}
}
The optional rendered property contains a function which gets called when a page has been rendered to the DOM.
rendered: function (pageName, wizards, data, context, $page) { {
let $elementWrap = wizards.getElementDiv("sampleInput");
$elementWrap.find("input").keypress(function(ev) {
if (ev.which == 13) {
// click the "finished" button when carrage-return is pressed on the text input
wizards._$finishBtn.click();
}
});
}
The build tool definition done property holds a method which is called in response to the user completeing a tool run in create mode (when in edit mode, the completed functionality is performed via a callback function in the edit property function).
An example of a done property method is...
"done": function(wizards, data, completeCB, context) {
// code to perform the actions required by this build tool
completeCB();
}
This function is asyncronous and once the operations have been completed the completeCB function should be called. This function can take a number of parameters detailed below.
The passed 1st wizards parameter gives access to various methods (see seperate sections below) to interact with the knowledge base's catalog. The 2nd data parameter is the completed data payload and the 4th context parameter holds extensive information concerning how the build tool is being operated (detailed seperatly).
As the done method is asyncronous, the completeCB function must be called to complete the tool run. The completeCB function can take several parameters to indicate back to the build tool framework any post-creation actions.
Example 1 - Build tool creates a branchable (e.g. Numeric) catalog object which is to be inserted onto a decision tree
If the build tool has either "tree" and/or "treebuild" in it's meta definition contexts, the tool should return a catalog object ID (to insert at the node the user has clicked on (or dragged onto).
completeCB(newObjectID, "multiway"); // n.b. The "split" element can populate the data payload with a valid split type
Note : If the split type is omitted, the new node is inserted as a "nosplit".
Example 2 - Build tool creates a catalog object which is to be inserted onto a decision tree as a no split and then opened for editing
completeCB(newDialogObjectID, null, true); // third parameter indicated "edit"
Example 3 - Build tool creates a Decision Tree Script Node
In this mode, the tool created a custom block (script node) which is inserted onto a decision tree. The tool can control the text displayed in the block, hold arbitrery data (for editing) and procude JavaSctipt code to run when encountered at runtime. This functionality relies on the xrkb.buildWizardTreeFunction method (see seperate section).
let funcCode = xrkb.buildWizardTreeFunction(
"Do Stuff",
context.definition.name,
{
workObjectID: data.workObject
},
"_dgo(" + data.workObject + ").val(42);"
);
completeCB(funcCode); // passing a String as the first parameter indicated that the tool has created a script node
Example 4 - Build tool created a new catalog object and creates a tree script node to operate on it
// The "workObject" element is a "hybrid" element with "allow_create" so we need to handle optional creation
if (!wizards.handleOptionalObjectCreation(data.workObject)) {
return;
}
wizards.performAsyncObjectCreation(function(newObjectList) {
// in case we have created a new object
data.workObject = wizards.handleOptionalObjectCreation_done(data.workObject, newObjectList);
// the "actionDescr" element is a "text" element
let funcCode = xrkb.buildWizardTreeFunction(
data.actionDescr,
context.definition.name,
{
caseIDobj: data.workObject
},
"_dgo(" + data.workObject + ").val(42);"
);
// return generated script node for insertion
completeCB(funcCode);
});
The build tool definition edit property holds a optional method which both informs the tool framework that the tool should be used for editing an existing object (or script node) and is called in response to the user initiating a tool run in edit mode.
An example of a edit property method is...
"edit": function (wizards, editObject, context, completeCB) {
// code to perform the actions required by this build tool
completeCB();
}
The passed 1st wizards parameter gives access to various methods (see seperate sections below) to interact with the knowledge base's catalog. The 2nd editObject parameter is either a catalog object or a tree script node settings object. The 3rd context parameter holds extensive information concerning how the build tool is being operated (detailed seperatly). The 4th completeCB parameter is the function to call once the edit operation has been fully completed.
The edit pattern usually consists of 3 steps..
This function is asyncronous and once the edit operation has been carried out, the completeCB function should be called.
Example 1 - Build tool provides an editor to modify the OnCapture event of an existing object
"edit": function(wizards, aObject, context, completeCB) {
// retrieve the existing code
let eventCode = $.isPlainObject(aObject.events) && aObject.events.OnCapture ? aObject.events.OnCapture : "";
let data = {}; // a new data payload
// work out the type of the existing code and populate the relevant payload property (to match page element names)
let scriptMode;
if (xrkb_tree.isFormula(eventCode)) {
scriptMode = "XpertScript";
data.editXScode = eventCode;
} else {
scriptMode = "JavaScript";
data.editJScode = eventCode;
}
// set the framework data payload
wizards.setData(data);
// show the page
wizards.renderPage(
scriptMode == "XpertScript" ? "edit_xs_page" : "edit_js_page", // start on the relevant page (based on script type)
function() {
// get the edited payload
let edited_data = wizards.getData();
// retrieve the script of the relevant input element
let newEventCode;
switch (scriptMode) {
case "XpertScript":
newEventCode = edited_data.editXScode;
break;
case "JavaScript":
newEventCode = edited_data.editJScode;
break;
}
// update the object
wizards.populateOnCaptureEvent(aObject.aID, newEventCode);
completeCB(aObject); // it's good practice to return the edited object (but not required)
}
);
}
Example 2 - Build tool provides an editor to modify a previously created Decision Tree Script Node
"edit": function (wizards, nodeSettings, context, completeCB) {
// "eObjectName" input element is of the "object"
// "eActionDescr" input element is of the "text"
let data = {
eObjectName: nodeSettings.data.caseIDobj, // the nodeSettings.data object is the object passed as the third param in the xrkb.buildWizardTreeFunction function
eActionDescr: nodeSettings.name // pull the display text of the node and allow the user to edit it
};
wizards.setData(data); // set the data payload for editing
wizards.renderPage(
"edit_page",
function (){
let edit_data = wizards.getData(); // get the edited data
// build the updated Decision Tree Script Node
let funcCode = xrkb.buildWizardTreeFunction(
edit_data.eActionDescr,
context.definition.name,
{
caseIDobj: edit_data.eObjectName
},
"_dgo(" + edit_data.eObjectName + ").val(xpertrule.cases.getTaskCaseID());"
);
completeCB(funcCode); // return a string for the framework to update the decision tree node
},
false // read & write
);
}
Once an edit is complete, it's often required to perform actions which are also performed by the create's "done" method. A good way to remove code duplicate is to call the tool's done method once the edit is complete. Here's an example of how to do this...
"done": function(params) {
let nodeData = {
sampleMode: data.mode ? data.mode : data.emode // as this can be called from the edit, the mode can come from 2 different controls
};
let code = xrkb.buildWizardTreeFunction(
data.name,
context.definition.name,
nodeData,
"xpertrule.doSomeFunction();"
);
completeCB(code);
},
"edit": function(wizards, treeNodeSavedData, context, completeCB) {
let self = this;
let nodeData = treeNodeSavedData.data;
let data = {
name: treeNodeSavedData.name,
emode: nodeData.sampleMode
};
/*
* render edit page
*/
wizards.setData(data);
wizards.renderPage(
"main_page",
function() {
let data2 = wizards.getData();
self.done(wizards, data2, completeCB, context); // reuse the tool's "done" function
}
);
}
Element widgets are the individual UI componants for a page. The definitions of these widgets is held in the elements array of the page definition in the pages property. To repeat the previous example...
pages: [
{
name: "initial_setup_page",
elements: [
<object describing a widget>,
<object describing a widget>
]
},
{
name: "confirmation_page",
elements: [
<object describing a widget>,
<object describing a widget>
]
}
]
Each individual element is represented by an object. An example of one of these widget elements might be...
{
"type": "text",
"name": "applicant_name",
"prompt": "Enter the name of the applicant",
"placeholder": "Applicant name goes here",
"optional": false
}
Each element requires a type property. This string describes the widget type (see table below for a full list).
The vast majority of elements will also have a unique name (the exception being for "header" widget which just displays some HTML). This is used as the key in the data payload object accociated with the tool execution. e.g. If the element name is "applicant_name" then (once completed by the user), the data object (passed into the next and done functions) will look something like...
{
applicant_name: "Arthur Dent"
}
The prompt for input elements is the HTML placed above the actual input. For display elements, the prompt is the HTML presented in the page.
The complete list of widget types is...
Widget Type | Description |
---|---|
header | A block of HTML shown on the page |
error | A block of HTML presented as a visual error (i.e. displayed in red) |
text | A standard input control for capturing plain text |
number | A standard input control for capturing numeric values |
pwd | A standard input control for capturing a password as plain text (i.e. input characters are hidden) |
list | A list of items to select from. The items are presented in full (i.e. not a dropdown) with a radio button or check box next to each value |
dropdown | A list of items to select from (presented as a dropdown list) |
textbox | A large multi-line area for capturing plain text |
checkbox | A standard checkbox for capturing boolean (yes/no) type inputs |
object | A dropdown list of Catalog Objects (filtered down by the build tool before presentation) for the user to select from |
objectlist | A large list of Catalog Objects (filtered down by the build tool before presentation) for the user to select from |
split | A dedicated widget for capturing the type of a descision tree split |
hiersplit | A dedicated widget for capturing the type of a hierarchy split (e.g. child / peer) |
tabs | A super-widget for presenting a collection of sub-elements as individual tab pages |
formula | A widget allowing for the creation and editing of XpertScript |
json | A widget allowing for the WYSIWYG editing of a JSON object |
html | A widget allowing for the creation and editing of HTML. This widget wraps the ckeditor package |
javascript | A widget allowing for the creation and editing of raw JavaScript. This widget wraps the codemirror package |
grid | A widget allowing for the display and editing of tabular data. This widget wraps the jsGrid package |
hybrid | An input widget which can capture either a literal (text) input or a Catalog Object reference |
uploadimg | An input widget allowing the user to upload an image to the platform server |
upload | An input widget allowing the user to upload a file to the platform server |
qr | A widget displaying a QR code for the supplied data (e.g. URL) |
Each of the above widgets accept various properties to define their functionality. There follows a comprehensive list of element widget types and their configuration properties.
All elements have a number of global properties. The only mandatory property is the type of the element, all other properties are optional...
property | description |
---|---|
visible | If set to false the element is initially hidden |
disabled | If set to true the element is disabled (pointer-events: none; opacity: 0.6) |
footer | HTML which if supplied is include below the input in a smaller font |
collapsable | If set to true the input is converted into a collapsable section. A toggle is appended to the prompt header which allows the user to control the input visibility |
style | An Object which if present is passed to the jQuery .css() method of the element. e.g. "style": {"font-size": "90%"} |
_class | If present, this String contains the class added to the element |
The header element is a simple block of HTML included on the page.
property | required | description |
---|---|---|
type | yes | "header" |
name | no | The name of the header element. This is only required if the element is going to be updated from the tool code via the wizards.setElementProp method |
prompt | yes | The HTML to include on the page |
Example
{
type: "header",
prompt: "Question Type"
}
The error element is similar to the header element in that it includes a simple block of HTML on the page. The error element apprears in a red style and defaults to not being visible.
property | required | description |
---|---|---|
type | yes | "error" |
name | yes | The name of the error element. The name can be used to update the error contents and/or show and hide the error from the tool code. See the wizards.setElementProp, wizards.showElement and wizards.hideElement methods for more details |
prompt | yes | The HTML to include on the page |
visible | no | Is the element initially visible (default == false). n.b. This is a different default for the global visible property |
Example
{
type: "error",
name: "name_error",
prompt: "Woops, something broke"
}
At it's most basic, the text element provides a simple text input box. There are however various optional settings which can further enhance it's functionality.
property | required | description |
---|---|---|
type | yes | "text" |
name | yes | The name of the text input element. The name can be used to reference the element (e.g. to show and hide the element via the tool code). The name is also used to represent the captured data in the data payload |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
placeholder | no | A String which if present is the placeholder text which is shown in the input control if it's empty |
readonly | no | Boolean defining whether the input read only (default == false) |
visible | no | Boolean defining whether the element initially visible (default == true) |
default | no | A String which if present is the initial default value used to pre-populate the input |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page until data has been provided |
editmodebtn | no | Boolean value which if true makes the input a "click to edit". In this mode the value is read only and the user must click a button to enable editing |
showCopyBtn | no | Boolean value which if true adds the "copy to clipboard" button on the right hand side |
showOpenBtn | no | Boolean value which if true adds the "open in a new tab" button on the right hand side. n.b. Only applicable if the input is designed to capture a valid URL |
action_button | no | An Object which if supplied describes a custom button added to the right hnad side of the input. See the details of the Object later in this section |
Example
{
type: "text",
name: "description",
prompt: "Item Description",
placeholder: "This is the text to display",
optional: true
}
The action_button functionality allows the tool to have a cusatomizable button added to the right of the text input. The configuration object supplied in the action_button property is...
property | required | description |
---|---|---|
icon | yes | The Semantic UI icon class String for the button's icon. See Semantic UI Icons |
title | no | If present, this String is used as the button's popup title |
_class | no | If present, this String contains the class added to the action button |
click | yes | This function is called in response to the button being clicked. The function declaration looks something like function(wizards, data, context, newValue) |
Example
action_button: {
icon: "calculator icon",
title: "Click here to add to total",
_class: "my-custom-btn",
click: function (wizards, data, context, newValue) {
if (!data.total_value) {
data.total_value = "";
}
data.total_value += newValue;
}
}
At it's most basic, the number element provides a simple numeric input box. All the text element properties are available (see above section) along with various other numeric-specific configutation properties. n.b. For number inputs, the data payload property for the input will be the "number" type and if a default is supplied for the element config this too should be a number (not a string).
property | required | description |
---|---|---|
type | yes | "number" |
name | yes | The name of the input element. For more details, see the text element section above |
decs | no | The number of decimal places for the input (default == 0) |
Example
{
"type": "number",
"name": "age",
"prompt": "Enter the applicant's age",
"placeholder": "Age in whole years last birthday",
"decs": 0
}
| pwd | A standard input control for capturing a password as plain text (i.e. input characters are hidden) | The pwd element provides a "password" input control. This type of control hides the character the user types. All the text element properties are available (see above section).
property | required | description |
---|---|---|
type | yes | "pwd" |
name | yes | The name of the input element. For more details, see the text element section above |
Example
{
"type": "pwd",
"name": "user_password",
"prompt": "Enter your password"
}
The list element presents a full visible list of items for the user to select from. If single-select then each item value has a radio button on the left, if multi-select each item value has a checkbox on the left. Individual items have an internal value name, a main block of HTML and an options extra block of HTML (presented under the main text in a smaller font).
property | required | description |
---|---|---|
type | yes | "list" |
name | yes | The name of the input element. For more details, see the text element section above |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
multisel | no | A Boolean which if true allows the user to select multiple values (default == false). n.b. For multi-select lists, the data payload property for the input will be an Array |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page until data has been provided |
emptyText | no | HTML which if present is displayed in the list if the values property is an empty array |
searchable | no | Boolean (default == false) which can add the text search functionality to the list |
initialFilter | no | Boolean (default === false) if the list is searchable, should the "filter" checkbox be checked on startup |
default | no | A String which if present is the initial default value used to pre-select the list. n.b. not compatible with multi-select list at present |
values | yes | An array of Objects describing each list value. See section below for more details |
height | no | If present either a Number representing the height of the list (in pixels) or a String "auto" to provide enough height to contain all the item values |
noCheckboxes | no | Boolean which if true removes the checkboxes and radio buttons from the list (to allow for a cleaner input, clicking the item still performs the select) |
allowOptional | no | An Object which if present provides the ability to have "optional" items. If supplied, a checkbox is placed at the bottom of the list with the supplied HTML next to it. The initial state is also supplied (either "visible" or "hidden"). e.g. allowOptional: {"prompt": "Show system modules", "default": "visible"}. The visibility of each item is controlled via the "optionalVisible" property added to each list value in the values property array |
Each Object in the values array can contain all the following properties...
property | required | description |
---|---|---|
name | yes | A unique String holding the internal value for this list item. This value name is used in the data payload and the default property |
prompt | yes | HTML used to prepresent this list value |
istitle | no | A Boolean which if true converts this item into just a list title (think of it as a seperator). If used as a title the font of the prompt is changed and no other properties are respected for this item |
extra | no | HTML which if present is included below the item's prompt in a smaller font |
visible | no | A Boolean which if false hides this item from the list |
optionalVisible | no | If the allowOptional property is being used in the main list definition, this Boolean controls whether the items is visible or hidden in response to the user checking the bottom box |
disabled | no | A Boolean which if true disallows the item from being selection |
Example
{
type: "list",
name: "auto_answer",
prompt: "Auto-answer this Question",
values: [
{
"name": "none",
"prompt": "No Auto-Answer"
},
{
"name": "script",
"prompt": "Calculated Question",
"extra": "This Question will be auto-answered via a Script assignment"
}
],
"default": "script"
}
The dropdown input allows the user to select item(s) from a dropdown list of available values. The input can be configured in various ways (e.g. optional, multi-select etc) as detailed below...
property | required | description |
---|---|---|
type | yes | "dropdown" |
name | yes | The name of the input element. For more details, see the text element section above |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
multisel | no | A Boolean which if true allows the user to select multiple values (default == false). n.b. For multi-select lists, the data payload property for the input will be an Array |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page until data has been provided |
empty | no | A String which if present is displayed in the dropdown list doen not contain any selected value(s) |
default | no | A String which if present is the initial default value used to pre-select the list. n.b. not compatible with multi-select list at present |
values | yes | An array of Objects describing each list value. See section below for more details |
upward | no | A Boolean which if true displays the popup list above the input box (default == downward). As of Version >= 5.4, if the dropdown is the last element on the page, upward defaults to true |
autofill | no | A String which can auto-fill the values with a specific list. At present the only option is "categories" which pre-populates the list with all the Catalog Categories |
Each Object in the values array can contain all the following properties...
property | required | description |
---|---|---|
name | yes | A unique String holding the internal value for this list item. This value name is used in the data payload and the default property |
prompt | yes | HTML used to prepresent this list value |
extra | no | HTML which if present is included below the item's prompt in a smaller font |
Example
{
type: "dropdown",
name: "dec_places",
prompt: "How many decimal places should this question have?",
"values": [
{
name: "0",
prompt: "0",
extra: "No dec places"
},
{
name: "1",
prompt: "1"
}
],
"default": "1"
}
The textbox input allows the user to provide plain text in a multi-line editor (i.e. an HTML textarea input).
property | required | description |
---|---|---|
type | yes | "textbox" |
name | yes | The name of the input element. For more details, see the text element section above |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
placeholder | no | A String which if present is the placeholder text which is shown in the input control if it's empty |
readonly | no | Boolean defining whether the input read only (default == false) |
visible | no | Boolean defining whether the element initially visible (default == true) |
default | no | A String which if present is the initial default value used to pre-populate the input |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page |
height | no | Number which if present representing the height of the textarea (in pixels) |
boxstyle | no | An Object which if present is passed to the jQuery .css() method of the textarea |
Example
{
type: "textbox",
name: "logValues",
prompt: "Supply a list of values for this question...",
placeholder: "First option\nSecond option\nThird option",
footer: "Enter each required value on its own line",
optional: true
}
The checkbox input allows the user to provide simple boolean (yes / no) data.
property | required | description |
---|---|---|
type | yes | "checkbox" |
name | yes | The name of the input element. For more details, see the text element section above. N.b. For checkboxed the property of the data payload is a JavaScript Boolean value |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
disabled | no | Boolean defining whether the input is disabled ot not (default == false) |
visible | no | Boolean defining whether the element initially visible (default == true) |
default | no | A Boolean which if present is the initial default value used to pre-populate the input |
Example
{
type: "checkbox",
name: "multiSelect",
prompt: "Is this question multi-select?",
optional: true
}
The object input allows the user to select from a list of Catalog Object which match one of the specified base class types. The user can (optionally un tool developer control) create a new object.
property | required | description |
---|---|---|
type | yes | "object" |
name | yes | The name of the input element. For more details, see the text element section above. N.b. For checkboxed the property of the data payload is a JavaScript Boolean value |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
placeholder | no | A String which if present is the placeholder text which is shown in the input control if it's empty |
multisel | no | A Boolean which if true allows the user to select multiple objects (default == false). n.b. For multi-select object elements, the data payload property for the input will be an Array |
disabled | no | Boolean defining whether the input is disabled ot not (default == false) |
visible | no | Boolean defining whether the element initially visible (default == true) |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page |
upward | no | A Boolean which if true displays the popup object list above the input box (default == downward) |
object_types | yes | An Array of Strings each of which specifies the name of an allowed Base Class. Each standard object (list, boolean, numeric, date, text) in the Object Catalog is based on a Base Class. Special Catalog Objects can also be allowed via the reserved pseudo-baseclass names... "NUM_ARRAY", "STR_ARRAY", "TXTPROCCESSOR", "HIERARCHY" and "REPORT". >= 5.3.1 The array can also contain object type constrants (e.g. TYPE_TEXT) to allow all objects of a specific type (rather than baseclass) |
allow_create | no | An optional Object which if present allows the user to create a new object (rather than selecting an existing). See seperate section below for more information |
The allow_create object allows the tool developer to give the user an oportunity to create a new object for an input.
property | required | description |
---|---|---|
placeholder | no | HTML (default = "Create a new object") which is included at the top of the Object Dropdown list to allow the user to start the creation process |
prompt | yes | HTML included as the title of the create section (above the name and category capture inputs) |
defaultName | no | A String which if supplied is used as the default for the new object's name |
defaultcat | no | A String which if supplied is used to default the Catalog category selection (if matching a valid category) |
baseclass | yes | A String holding the name of the base class of the new object. n.b. if the class is missing from the Knowledge-Base it is automatically imported |
Example
{
type: "object",
object_types: ["Text_Question", TYPE_TEXT],
name: "objectName",
prompt: "Select an object to hold the new Case ID",
placeholder: "Select an object",
allow_create: {
placeholder: "Create a new object",
prompt: "New Case ID object details...",
baseclass: "Text_Question",
defaultName: "CaseID"
},
"footer": "This [text] object will hold the Case ID of the newly created case"
}
The objectlist input (similar to the object input) allows the user to select from a list of Catalog Objects. Note that the allow_create functionality of the object input IS NOT available in the objectlist. However, the tool developer has more control over the contents of the list as well as making it searchable.
property | required | description |
---|---|---|
type | yes | "objectlist" |
name | yes | The name of the input element. For more details, see the text element section above. N.b. For checkboxed the property of the data payload is a JavaScript Boolean value |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
multisel | no | A Boolean which if true allows the user to select multiple objects (default == false). n.b. For multi-select object elements, the data payload property for the input will be an Array |
searchable | no | Boolean (default == false) which can add the text search functionality to the list |
initialFilter | no | Boolean (default === false) if the list is searchable, should the "filter" checkbox be checked on startup |
disabled | no | Boolean defining whether the input is disabled ot not (default == false) |
visible | no | Boolean defining whether the element initially visible (default == true) |
optional | no | Boolean defining whether the input required or optional? If not optional then the user cannot progress from the page |
empty | yes (if optional == true) | This HTML is added to the top of the list if the input is set as optional to allow the user to select nothing |
allow | no | A Function which if supplied is called multiple times to allow the tool developer to provide code which specifies whether individual Catalog Objects are included into the list. The function might look something like function(catalogObject, data, context) and should return a boolean value to indicate inclusion |
object_types | yes (if allow == false) | If the allow function is not supplied, this property is an Array of Strings each of which specifies the name of an allowed Base Class. Each standard object (list, boolean, numeric, date, text) in the Object Catalog is based on a Base Class. >= 5.3.1 The array can also contain object type constrants (e.g. TYPE_TEXT) to allow all objects of a specific type (rather than baseclass) |
Example
{
type: "objectlist",
name: "att",
prompt: "Select a question to add knowledge to...,",
style: {
"flex": "1 0"
},
multisel: false,
optional: false,
searchable: true,
allow: function (aObject, data, context) {
if (aObject.aTree || aObject.aExamples || aObject.aFlow) {
return false; // do not allow selection of object which have knowledge
}
switch (aObject.aType) {
case TYPE_LIST:
case TYPE_BOOLEAN:
case TYPE_NUMERIC:
case TYPE_TEXT:
case TYPE_DATE:
if (aObject.flatProps.pid) {
return true; // if pid is set then this object is NOT a baseclass
}
}
return false; // reject all other objects
}
}
The split input is a highly specific element for allowing the type of decision tree split to produce when adding an object to a tree. An example of it's use is when the Add New Question (xrSuperQuestion) tool is started via the popup menu on a decision tree.
property | required | description |
---|---|---|
type | yes | "split" |
name | yes | The name of the input element. The data payload is a string (which is intended to be passed to the completion function from the done method). For more details, see the "done" method section |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
allow | yes | An Array of strings which specifies the allowed type of splits for the user to select from. Possible values are "nosplit", "single" and "multiway". Note that only certain split types are applicable to certain Object values (e.g. "single" split is not available for Numeric Objects) |
default | no | A String which if present pre-selects the chosen split type |
Example
{
type: "split",
name: "split_type",
prompt: "What type of split would you like to create in the tree?",
allow: ["nosplit", "single", "multiway"],
default: "multiway"
}
The hiersplit input is a highly specific element for allowing the type of hierarchy split to produce when adding an object to a hierarchy (similar to the tree "split" input element detailed previously). An example of it's use is when the Add New Question tool is started via the popup menu on a hierarchy.
property | required | description |
---|---|---|
type | yes | "hiersplit" |
name | yes | The name of the input element. The data payload is a string (which is intended to be passed to the completion function from the done method). For more details, see the "done" method section |
prompt | yes | The HTML which is included above the input control to inform the user of what is being captured |
allow | yes | An Array of strings which specifies the allowed type of splits for the user to select from. Possible values are "peer", "child" |
default | no | A String which if present pre-selects the chosen split type |
Example
{
"type": "hiersplit",
"name": "split_type",
"prompt": "What type of insert would you like to perform?",
"allow": ["peer", "child"],
"default": "peer"
}
The tabs element is an element used to produce a collection of tab sheets. Each sheet has a title (displyed at the top of the control for the user to click on to select the relevant sheet). Each sheet also a has list of sub-elements which define the contents of each individual sheet. An example of the tabs element is the edit_page of the xrSuperQuestion build tool.
property | required | description |
---|---|---|
type | yes | "tabs" |
name | no | The name of the main tabs element is only required to provide programatic access from the build tool code |
tabs | yes | An Array of tab sheet objects. Each item in the array represents an individual sheet. The schema of the tab sheet Object is detailied below |
Each element in the "tabs" Array property (see above) holds the definition of an individual tab sheet.
property | required | description |
---|---|---|
title | yes | HTML used in the render of the individual tab sheet name |
name | no | The name of this individual tab sheet. Only required to provide programatic access from the build tool code |
visible | no | A Boolean which if present allows individual tab sheets to be shown or hidden. n.b. If all sheets are hidden, an error will be thrown |
active | no | A Boolean which if true shows this sheet as the initially selected. n.b. If not sheet is flagged as active, the first visible sheet will be the initially shown |
style | no | An Object which if present is passed to the jQuery .css() method of the sheet div. e.g. "style": {"font-size": "90%"} |
elements | yes | An Array of Element Widget Definitions. This array is exactly the same format as the main elements array for a build tool page |
Example
{
type: "tabs",
name: "main_tabs",
tabs: [
{
title: "First Tab",
name: "tab1_name",
visible: true,
active: true,
elements: [
{
type: "text",
name: "description",
prompt: "Item Description"
}
]
},
{
title: "Second Tab",
name: "tab2_name",
visible: true
elements: [
{
type: "textbox",
name: "log_values",
prompt: "Supply a list of values...",
placeholder: "First option\nSecond option\nThird option"
}
]
}
]
}
The formula element places a full XpertScript editor onto the page.
property | required | description |
---|---|---|
type | yes | "formula" |
name | yes | The name of the input element. The data payload is an encoded string which can be used (via build tool code) to populate Catalog Object script elements (e.g. Procedure Catalog Object, Decision Tree Code Block, Catalog Question Events) |
thisID | no | A Number which if present holds the ID of the Catalog Object associated with this XpertScript. This ID is used to allow the user to write generic code which references the Catalog Object that it is associated with. An example of this is the Calculated Question tool (xrCalculation) where in the default code "Assign < Catalog Name > = < value >" the < Catalog Name > is a soft reference to the containing object. This allows thew user to copy and paste the exact same code between different calculated questions (if required) |
thisname | no | A String which if present (and the thisID property is not supplied) allows the user to select a special "this" pseudo-object from the formula editor. If supplied, the thisType property must also be supplied |
thisType | yes (if thisname is supplied) | When the thisname is supplied, this property holds one of the following constants to specify the type of the pseudo-object... TYPE_LIST, TYPE_MLIST, TYPE_NUMERIC, TYPE_BOOLEAN, TYPE_DATE |
thisdecs | no | A Numeric which if supplied (and thisname is supplied and thisType == TYPE_NUMERIC) specifies the number of decimal places for the pseudo-object |
thisValues | no | An Array of Strings which if supplied (and thisname is supplied and thisType == TYPE_LIST or thisType == TYPE_MLIST) specifies the list values for the pseudo-object |
Example
{
type: "formula",
name: "my_code",
prompt: "Build your formula here...",
"default": '{"lines":[{"cmd":"let","targetID":-1,"expr":{"type":"list","items":[{"type":"num","value":0}]}}]}',
thisname": "This",
thisType": TYPE_NUMERIC
}
The json element places a WYSIWYG JSON editor onto the page. The editor can be given a JSON string (including ones containing calculations) or a JSON object (in which case calculations / references are not used).
property | required | description |
---|---|---|
type | yes | "json" |
name | yes | The name of the input element. The data payload is usually a JavaScript string holding a JSON object. The idea is that this is included as-is into generated coded (e.g. Procedure Catalog Object, Decision Tree Code Block, Catalog Question Events) |
Note: If the user selected a property to be a catalog reference, the returned code (in the data payload) will be translated to _dgo lookups. The reverse is also true in that if the initialization data has basic _dgo(nn).val() references, these are handles in WYSIWYG mode (otherwise the editor starts in RAW mode).
Example
{
type: "html",
name: "my_json_script",
prompt: "Build your JSON here...",
"default": "{\"name\": \"Joe Bloggs\", \"age\": 22}"
}
The html element places a full ckeditor HTML editor onto the page. An example can be seen in the xrReport build tool.
property | required | description |
---|---|---|
type | yes | "html" |
name | yes | The name of the input element. The data payload is an string holding the produced HTML |
default | no | A String which if present is the initial default HTML used to pre-populate the ckeditor control |
Example
{
type: "html",
name: "my_report",
"default": "Your report goes here..."
}
The javascript element places a full codemirror JavaScript editor onto the page. An example can be seen in the xrCalculation build tool.
property | required | description |
---|---|---|
type | yes | "javascript" |
name | yes | The name of the input element. The data payload is an string holding the produced HTML |
default | no | A String which if present is the initial default HTML used to pre-populate the ckeditor control |
Example
{
type: "javascript",
name: "my_code",
prompt: "Build your script here...",
footer: "Tip: Use Ctrl-Space to trigger code completion."
}
The grid element places a full jsGrid control onto the page. The input widget exposes a large amount of the jsGrid functionality (which will not be documented here) but can be read in the official jsGrid documentation.
property | required | description |
---|---|---|
type | yes | "grid" |
name | yes | The name of the input element. The data payload is an Array of Objects holding the individual rows of the grid. The property names should match the name property of the field definition. See the fields definition below |
fields | yes | An array of Objects following the jsGrid documentation to specify the format of column |
noAdding | no | A Boolean which if true removes the abaility for the user to add new rows |
optional | no | Boolean defining whether the grid must have at least 1 row |
noDragging | no | Should the grid allow the rows to be reordered (default = do not allow dragging) |
allowDeleting | no | Should the grid allow rows to be deleted (default = do not allow row deleting) |
sorting | no | Add the ability sort the grid via column click (default = false) |
rowCountSelector | no | CSS selector to update with the number of rows (e.g. "#rowCnt"). Used in xrSuperQuestion List Question Editor to update the tab heading |
minFieldWidth | no | By default, all columns which do not have an explicit width are equally spaced to make the entire grid fit (horizontally). This can result in very narrow columns (e.g. list value prop grid with lots of props). This optional numeric property limits the minimum width of auto-sized columns |
Example
{
"type": "grid",
"name": "key_val_obj",
"prompt": "Please supply your property key values pairs",
"fields": [
{type: "control", deleteButton: true, width: 52},
{name: "key", title: "Key", type: "text"},
{name: "value", title: "Value (Test Value)", type: "text"},
{name: "objectName", title: "Tied Catalog Item", type: "select", valueField: "Id", textField: "Name"}
],
footer: "User, you have the helm",
noAdding: false,
optional: true
}
Tip: When a field is designed to capture a Catalog Question (via a "select" field type), the tool can add population code (i.e. the list of items to select from) via custom code the next method. This code might look something like...
// Add objects of type LIST or BOOLEAN to the "objectName" field
let grd = wizards.findElementByName("key_val_obj"); // find the definition of the element
let fld = grd.fields[grd.fields.length - 1]; // store a reference to the last field
fld.items = [{Name: "", Id: 0}]; // The items property of the field definition holds the items to select from
for (let c = 0; c < dictionary.aDictionary.length; c++) {
let o = dictionary.aDictionary[c];
switch (o.aType){
case TYPE_LIST:
case TYPE_BOOLEAN:
// allow non-baseclass objects of type LIST or BOOLEAN
if (o.flatProps.pid && !o.aTree && !o.aExamples && !o.aFlow) {
fld.items.push({Name: o.aName, Id: o.aID});
}
break;
}
}
The hybrid element places an input widget on the page to enter either (1) text literal or (2) select an existing Catalog Object. The 2 modes are switched (by the user) from buttons on the right of the input.
(>= V5.2 only) The ability to treat the literal as a numeric (but still represented interallly as a string)
property | required | description |
---|---|---|
type | yes | "grid" |
name | yes | The name of the input element. The data payload is either a Number (if a catalog object is selected) or a String (if plain text is supplied) |
allowed | yes | At present, must be either "text" or "number". n.b. If "number", the data value is still held as a string |
default | no | If a String is supplied (even an empty string) then the input starts in plain text mode. If a Number is supplied, the input starts in Catalog Object mode with the relevent question selected (by ID) |
decs | no | If allowed ="number", this is the number of decimal places (defaults to 0) |
Example
{
"type": "hybrid",
"name": "api_key",
"prompt": "Supply the API key to access this service",
"allowed": "text",
"footer": "Select between plain text or catalog object",
"default": "" // default to empty literal text; use 0 to default to empty object selection
}
{
"type": "hybrid",
"name": "ageInput",
"prompt": "Supply the age",
"allowed": "number",
"footer": "Select between literal number or catalog object",
"default": "42", // default to "42.00"
"decs": 2
}
The uploadimg element placed an HTML form on the page. This form posts to a specified (build tool supplied) URL. The element displays the image as a thumbnail (if pre-supplied or recently uploaded). The URL for the form POST should return a JSON object with a Boolean "ok" property, an "error" string (if ok == false) or a "url" string if ok == true.
property | required | description |
---|---|---|
type | yes | "uploadimg" |
name | yes | The name of the input element. The data payload is the URL returned in the "url" property of the upload script |
width | yes | A Number specifying the width in pixels of the tuumbnail |
height | yes | A Number specifying the height in pixels of the tuumbnail |
url | yes | A String specifying the POST action URL. This script will receive a multipart/form-data form with the fieldname supplied name of the file data and any additional params supplied in the element definition |
params | no | An optional array of Object describing additional HTML hidden inputs added to the upload form. Each object has 2 properties "name" and "value". Note, these can be modified in Build Tool code |
fieldname | yes | The name of the file field posted in the HTML form |
default | no | If a String is supplied this is the initial pre-populated URL for the image |
Example
{
type: "uploadimg",
name: "up_image",
prompt: "Supply an icon for this tool...",
width: 24,
height: 24,
url: "/libraries/wizards/toolup.php",
params: [
{
name: "fieldname",
value: "myimage"
},
{
name: "opmethod",
value: "imageup"
}
],
fieldname: "image",
footer: "Icons should be in PNG format and measure 24 X 24 pixels",
"default": "images/tag.png"
}
The upload element is similar to the uploadimg input in that an input is placed on the page for the user to upload a file. This form posts to a specified (build tool supplied) URL. The element displays a box for the user to interact with and provides feeback on upload success. The URL for the form POST should return a JSON object with a Boolean "ok" property, an "error" string (if ok == false) or a "url" string if ok == true.
property | required | description |
---|---|---|
type | yes | "upload" |
name | yes | The name of the input element. The data payload is the URL returned in the "url" property of the upload script |
url | yes | A String specifying the POST action URL. This script will receive a multipart/form-data form with the fieldname supplied name of the file data and any additional params supplied in the element definition |
params | no | An optional array of Object describing additional HTML hidden inputs added to the upload form. Each object has 2 properties "name" and "value". Note, these can be modified in Build Tool code |
fieldname | yes | The name of the file field posted in the HTML form |
Example
{
type: "upload",
name: "csv_file",
prompt: "Select your CSV data file for training",
url: "libraries/wizards/fileup.php",
params: [
{
name: "filemode", // a hidden "filemode" HTML input
value: "training"
}
],
fieldname: "afile" // this is the name of the "file" HTML input
}
The qr element adds a QR code to the page representing the data held in name property of the data payload. Note that the data property must be pre-populated with the appropriate data to encode!
property | required | description |
---|---|---|
type | yes | "qr" |
name | yes | The name of the element. This property (in the data payload object) holds the data to encode |
Example
{
type: "qr",
name: "deployed_url"
}
Many methods (e.g. start_page, next, done) are passed a wizards object. This object provides a number of methods which allow the build tool developer easy access to modify the page definition and / or perform Catalog Object operations.
wizards Method | definition | Description |
---|---|---|
showElement | wizards.showElement("element name"); | Show an element on a page given it's element name |
hideElement | wizards.hideElement("element name"); | Hide an element on a page given it's element name |
enableElement | (>= V5.2 only) wizards.enableElement("element name"); | Enable an element on a page given it's element name |
disableElement | (>= V5.2 only) wizards.disableElement("element name"); | Disable an element on a page given it's element name |
setElementProp | wizards.setElementProp("element name", "element property", "element value"); | Set a given property on a named element. e.g. wizards.setElementProp("error_box", "prompt", "You made an error"); |
getElementProp | let elPropValue = wizards.getElementProp("element name", "element property"); | Get a given property value on a named element. e.g. wizards.let curErr = getElementProp("error_box", "prompt"); |
showWorking | wizards.showWorking("message"); | Disable the UI, adding a spinner and a supplied message |
hideWorking | wizards.hideWorking(); | Enable the UI after a showWorking call |
isCurrentDeployTarget | let isVal = wizards.isCurrentDeployTarget("target name"); | Return a Boolean representing whether a specific deployment mode is enabled by the user on the Knowledge-Base Settings dialog. Possible target names are "chat", "dialog" or "silent" |
showElementValue | wizards.showElementValue("list element name", "list element value name"); | Show an individual named list value in a specific list input element |
hideElementValue | wizards.hideElementValue("list element name", "list element value name"); | Hide an individual named list value in a specific list input element |
showAllElementValues | wizards.showAllElementValues("list element name"); | Show all list values in a specific list input element |
findElementByName | let aDef = wizards.findElementByName("element name"); | Find the element definition object of the specified element by name |
findTabByName | let sheetDef = wizards.findTabByName("tabs element name", "tab sheet name"); | Find the sheet definition object of the specified sheet on the specified tabs element |
hideTab | wizards.hideTab("tabs element name", "tab sheet name"); | Hide a specific sheet on the specified tabs element |
showTab | wizards.showTab("tabs element name", "tab sheet name"); | Show a specific sheet on the specified tabs element |
setActiveTab | wizards.setActiveTab("tabs element name", "tab sheet name"); | Set the active (visible) sheet of the specified tabs element |
getActiveTab | let actTabName = wizards.getActiveTab("tabs element name"); | Get the name of the currently active (visible) tab sheet |
In the done method, it's often required to create new catalog objects. This is done by adding create and import operations to a queue and then making a final call to perform the actual creation.
The handleOptionalObjectCreation method is required when an object element is included in the tool with the allow_create functionality. The build tool should call this method before making the call to the performAsyncObjectCreation method. The function takes just a single parameter (from the data payload) of the captured element. e.g. if the tool contains an object type element with a name of "newObjectName" with the allow_create supplied in the element definition, the following would prepare the framework in preperation for the subsequent performAsyncObjectCreation call.
if (!wizards.handleOptionalObjectCreation(data.newObjectName)) {
return;
}
The creationObjectAsync method prepares the framework to create a new Catalog Object. The method takes a configuration object which has the following properties
property name | required | description |
---|---|---|
name | yes | The name of the new Catalog Object (must be unique) |
baseclass | yes | Either a String representing the name of the Base Class to create the question from, or, a constant preresenting a non-question object (e.g. REPORT). If this property is a String and the base class does not exist in the knowledge base, it is automatically imported from the libraries/objects folder |
catID | no | A number which if supplied is the ID of the catalog category which the new object lives in. If omitted (or -1) the object is placed in the "uncategorized" category |
varType | yes (if baseclass == -TYPE_VARIABLE) | Constant of VARTYPE_STR or VARTYPE_NUM. See xrArray tool for more information |
dims | no | A Number (0 or 1) which signifies whether the catalog variable is an array |
descr | no | A String which if supplied is used to populate the new object's description |
supressWizAssoc | no | A Boolean which if true does not associate the new Catalog Object with this build tool. This primerily used where a tool creates a suplimental object to hold some kind of value which is utilized by the code produced by the tool (this is the default functionality for the handleOptionalObjectCreation method) |
dlgParent | no | A Number holding the optional ID of a parent dialog (when baseclass == -TYPE_DIALOG). See the xrDialog tool for more information |
As mentioned above, the baseclass property holds either the name of a base class question, or a constant. Possible constant values are... -TYPE_REPORT, -TYPE_DIALOG, -TYPE_VARIABLE, -TYPE_CATEGORY, -TYPE_PROCEDURE, -TYPE_HIERARCHY.
Example
let categoryID = !data.categoryName ? -1 : parseInt(data.categoryName, 10); // convert from string to number
if (!wizards.creationObjectAsync({
name: data.newObjectName,
baseclass: data.baseClass,
catID: categoryID})) {
return;
}
The importObjectAsync method prepares the framework to create a new ( usually a base class ) Catalog Object based on an object held in the libraries/objects folder. The method takes a configuration object which has the following properties
property name | required | description |
---|---|---|
name | yes | The name of the object to import. This is the filename of the json definition held in the libraries/objects folder |
catID | no | A Number which if supplied specifies the Catalog category ID used to hold the new object. n.b. Base classes should not be associated with a category so leave this parameter empty of 0 |
The importProcedureAsync method prepares the framework to create a new Catalog Procedure Object based on an object held in the libraries/procedures. The new procedure is marked as read only. The method takes a configuration object which has the following properties
property name | required | description |
---|---|---|
name | yes | The name of the procedure to import. This is the filename of the js file held in the libraries/procedures folder |
catID | no | A Number which if supplied specifies the Catalog category ID used to hold the new object. n.b. Base classes should not be associated with a category so leave this parameter empty of 0 |
runOnServer | no | A Boolean which if true flags the newly imported procedure to "Run On Server" |
The performAsyncObjectCreation method performs the all the operations previously supplied by calls to handleOptionalObjectCreation, creationObjectAsync, importObjectAsync and importProcedureAsync. As the name suggests, this is an asyncronous operation and the method is therefore passed a function which is called on completion of the operation. This callback function is passed an object which holds the names and IDs of the newly created objects.
Example
wizards.creationObjectAsync({name: data.newObjectName, baseclass: "Text_Question", catID: -1}); // create new object named from data.newObjectName
wizards.performAsyncObjectCreation(function(newObjects) {
let newObjectID = newObjects[data.newObjectName];
// more code here
wizards.setObjectStyle(newObjectID, context.definition); // style the new object
completeCB(newObjectID); // finish the "done" method
});
The handleOptionalObjectCreation_done is used in conjunction with the "allow_create" functionality of the "object" element and the wizards.handleOptionalObjectCreation method. It is used in the following pattern whereby if a new object has been created, it's name if placed in the data payload ( if an existing object is selected, )
data.objectName = wizards.handleOptionalObjectCreation_done(data.objectName, list);
Example
wizards.handleOptionalObjectCreation(data.referencedObject); // "referencedObject" is an "object" element with "allow_create" set
wizards.performAsyncObjectCreation(function(newObjects) {
data.referencedObject = wizards.handleOptionalObjectCreation_done(data.referencedObject, newObjects);
// data.referencedObject holds the ID of either the selected existing catalog object or the newly created object
...
});
The addListValue method takes the ID of a Catalog List Question and adds a new List Value to it. The new value can also ( optionally ) contain extra list value properties. Note that if supplying value properties, these should have previously been added via the addListValueProperty method ( see below for details ).
Example
wizards.addListValue(newObjectID, "Value 1", {cost: 42.57});
The addListValueProperty method is used to add list value property definitions to an existing List Question. Once the properties have been defined, they can be populated via the optional 3rd parameter on the addListValue method. The parameters for the addListValueProperty method are (objectID, newPropertyName, newPropertyType, newPropertyDescription). Available types are "str", "bool", "int" and "float".
Example
wizards.addListValueProperty(newObjectID, "NewListProp", "str", "New list property");
The setObjectStyle method set the visual style of a specified Catalog Object to that of the a build tool. The build tool style is held in the @style meta definition.
Example
wizards.setObjectStyle(newObjectID, context.definition); // copy the object's catalog style from the wizard definition style
The findWizardByName method finds the index of a given wizard. The method returns -1 if the wizard name is not found, otherwise, the returned index can be used to retrieve the wizard definition via the wizards.items Array.
Example
// Make the new object visually appear as though created via the "xrCalculation" build tool
let newObject = _dgo(newObjectID); // find the catalog object by ID
let wizIdx = wizards.findWizardByName("xrCalculation");
newObject.objInfo.wiz = wizards.items[wizIdx].name;
newObject.objInfo.icon = wizards.items[wizIdx].icon;
newObject.objInfo.style = wizards.convertWizStyleToObjStyle(wizards.items[wizIdx].style);
The following methods are used in the done and edit methods to perform specific actions on existing Catalog Objects.
The populateProcedure method is used to populate the contents of an existing procedure catalog object. The method takes 2 parameters (procedureID, procedureCode). The actual code is usually taken from either a "formula" or "javascript" element populated data payload string, but it's also common to pre-supply template code or use code produced from other build tool inputs.
Example
// Assume 3 data payload properties
// "langType" is a "list" allows the user to determine whether they would like to use JavaScript or XpertScript
// "jsCode" element is a "javascript" input
// "xrCode" input is a "formula" element
switch (data.langType) {
case "js":
wizards.populateProcedure(newProcedureID, data.jsCode);
break;
case "xs":
wizards.populateProcedure(newProcedureID, data.xrCode);
break;
}
The populateReport method (similar to the populateProcedure method) populates the body of an existing Report Catalog Object. The method takes 2 parameters (reportID, reportBody).
Example
// Assume that "reportBody" is an "html" input element
wizards.populateReport(newReportID, data.reportBody);
The populateOnCaptureEvent method (similar to the populateProcedure method) takes some code (JavaScript or XpertScript) and uses it to populate the OnCapture event of a specified Catalog Question Object. The method takes 2 parameters (questionID, procedureCode)
Example
// Add OnCapture code to the new question to set it's value to 42
wizards.populateOnCaptureEvent(newQuestionID, "self.val(42);");
The buildWizardTreeFunction method OF THE XRKB OBJECT is used when the build tool is used to create a Decision Tree Script Node. This method creates the custom code (to return to the next complete function). The custom code holds custom text (to display on the tree), an object to hold edit data (perhaps the data payload) and the actual JavaScript to perform the operation! See xrCaseMgmtGetTaskCaseID for an example! The method takes 4 parameters (nodeDescription, wizardName, editDataObj, javaScriptString).
Example done Code
// Assume we have an "object" element called "workObject". This code sets it's value to 42 in this tree node
let funcCode = xrkb.buildWizardTreeFunction(
"Do Stuff",
context.definition.name,
{
workObject: data.workObject
},
"_dgo(" + data.workObject + ").val(42);"
);
completeCB(funcCode);
n.b. This type of build tool is very intuative for the user in that the nodeDescription can describe what the step does, and, it can operate on an appropriatly named (usually by the user) catalog object.
When the build tool is used to edit an existing object (or a tool build decision tree node) via the "edit" method, there are 3 special wizards methods used to integrate with the framework. See xrCaseMgmtGetTaskCaseID for an actual (simple) example of the actual pattern to use.
The setData method populates the data payload in preperation to present the user with the edit page. It takes a single parameter which is the payload data.
Example
// This code is an example of editing a tool-created decision tree script node
// Some previous (done) code has called the xrkb.buildWizardTreeFunction method with a data payload of {workData: <object id>}
// The edit page of the tool has an "object" element called "eWorkObject"
let data = {
eWorkObject: treeNodeSettings.data.workObject
};
wizards.setData(data);
The renderPage is used to inform the framework to render the speficied (edit) page. It can take up to 4 parameters (toolPageName, completeCallbackFn, readOnly, postRenderCallbackFn).
parameter name | required | description |
---|---|---|
toolPageName | yes | A String holding the name of the page to render (as held in the pages property of the build tool definition) |
completeCallbackFn | yes | A Function which is called in response to the user clicking the done button. See below for more details |
readOnly | yes | Boolean speficying whether all the inputs should be made read only |
postRenderCallbackFn | no | An optional Function which is called once the page has actually beed displayed. The function is passed a single parameter which is the jQuery object of the DIV of the rendered page |
The completeCallbackFn Function does not get passed any parameters and is called when the user clicks the DONE button on the edit page. The build tool should implement this function to retrieve the edited data payload (via wizards.getData) and perform any required catalog (or decision tree node script) actions!
Example
wizards.renderPage(
"edit_page",
function (){
// called when user is done, perform actions
completeCB(); // complete the framework edit operation
},
false
);
The getData method is used within the completeCallbackFn callback function to retrieve the editied data payload. This data is used to perform the actual edit operation of which the most common actions are...
When editing catalog objects, methods such as wizards.populateOnCaptureEvent are mode commonly used. For Tree Script Nodes, the xrkb.buildWizardTreeFunction method is called and the resulting code passed to the completeCB function (to inform the framework to update the node).
Example
// The edit page of the tool has an "object" element called "eWorkObject"
wizards.renderPage(
"edit_page",
function (){
var data2 = wizards.getData(); // get the edited data payload
let funcCode = xrkb.buildWizardTreeFunction(
"Do Stuff",
context.definition.name,
{
workObject: data.eWorkObject
},
"_dgo(" + data.eWorkObject + ").val(42);"
);
completeCB(funcCode);
},
false
);
This section details additional help which has proven useful in building real-world custom build tools
When a build tool is designed to be used in the decision tree editor toolbar (as a custom button), there are some aspects of the context object (passed to the various methods) which are very useful in implementing tree-specific functionality...
The context.knowledgeObject is a reference to the edit buffer's current object. This is the COPY of the dictionary object currently being edited. Changes to the tree object (be it the tree it'self, it's outcomes or it's control properties) should be made to this passed object (rather than looking up the object in the dictionary).
The populate.allow build tool method can be used (in conjunction with the knowledgeObject property) to control on which trees the tool should appear (e.g. Only show the tool if the tree is a specific type was originally created by a specific build tool)
(> V5.2 only) The context.selectedNode holds a reference to the currently selected (in the editor) decision tree node
The build tool done method can perform a wide variety of operatings on the tree being edited. Some examples can be seen in the folowing code...
"done": function(wizards, data, completeCB, context) {
// the tool can modify (in this example, clear) the tree
context.knowledgeObject.aTree = {
aID: xrkb_tree.getNextNodeID(),
aType: NODETYPE_LEAF,
aOutcome: xrkb_tree.createEmptyOutcome()
};
// we can add an object to the current editor's object palette
xrkb_tree.currentAttList.push({
aID: _dgobn("Sample_Question").aID,
used: 0
});
// V5.2 Only : We always need to call completeCB, but for "treetoolbar" context passing **true** as the first parameter sets the editor modified flag and updates the entire display
completeCB(true);
}
Build tools sometimes need to interact with the platform in ways outside the scope of the framework. In this case additional platform methods can be called to achieve any and all actions required. An example of a platform method is the xrkb.buildWizardTreeFunction method (described previously). This section is a catch-all for other commonly used platform functionality.
The xrkb.version property holds a String which represents the version number of the platform. e.g.
if (parseFloat(xrkb.version) >= 5.2) {
wizzards.hideElement("action_description");
}
It is possible to perminantly store additional data along with each viabl.ai catalog item. This is useful in (but not limited to) the following scenarios...
The extra data is access via the [catalog object].extraData() method. e.g.
// Store extra data with the "Grade" catalog object
#Grade.extraData({salary: "B", uplift: 1.2});
// Retrieve extra data associated with the "Grade" catalog object
let exData = #Grade.extraData();
// From Catalog Object EVENT scripts (e.g. OnCapture), we can use the "self" variable to retrieve the object's data...
let mySettings = self.extraData();
n.b. If an object is stored with the catalog object, the retrieve operation returns the actual stored data object (i.e. a reference). This means that any modifications to the retrieved data are perminantly associated with the catalog object
Build tool often need to build "configuration" objects for passing on to library functions (or working directly from them). The build tool code often looks better (and is less prone to parsing / escaping issues) if the config object is built by the tool and then passed to JSON.stringify to procude the generated code. This works well for static (number, string etc) config properties but not for when the tool can accept a "tied" object to retrieve the value from (e.g. A "hybrid" input control). Fortunatly, the wizard framework has 3 methods which help with this problem...
Let's assume we have a build tool with 2 hybrid inputs ("keyVaultName" and "secretName"). These are used (along with a text "tenantIDname" input) to build a configuration object which is included in the generated OnCapture event code. As documented, a hybrid input returns either a string (if a literal value) or a number (for an object reference). We can simply build the configuration object with the following code...
let keyVaultSettings = {
tenantIDname: data.tenantIDname,
keyVaultName: typeof data.keyVaultName == "number" ? wizards.getObjectByValue(data.keyVaultName) : data.keyVaultName,
secretName: typeof data.secretName == "number" ? wizards.getObjectByValue(data.secretName) : data.secretName
};
Note the wizards.getObjectByValue function (if the input is an object reference). This function actually returns a special string identifier to include as the property's value. There is also a wizards.getObjectByReference function which returns a string identifier to represent getting an object's reference (rather than it's value).
Once the configuration object has been constructed, it can be converted into (generated) code via the wizards.processMessage(configObj) function. So the complete example might look like this...
// build the config object
let keyVaultSettings = {
tenantIDname: data.tenantIDname,
keyVaultName: typeof data.keyVaultName == "number" ? wizards.getObjectByValue(data.keyVaultName) : data.keyVaultName,
secretName: typeof data.secretName == "number" ? wizards.getObjectByValue(data.secretName) : data.secretName
};
// create the onCapture code
let onCaptureEventCode = `self.val(_dgo(${importedLibraryID}).run(${wizards.processMessage(keyVaultSettings)}));`;
// Populate the onCapture event
wizards.populateOnCaptureEvent(newObjectID, onCaptureEventCode);
The actual (generated) code in the above example might look something like this...
self.val(_dgo(${importedLibraryID}).run({
"tenantIDname": "my tenant name",
"keyVaultName": _dgo(42).val(),
"secretName": "my secret name"
}));