Using JavaScript Procedures | Referencing Objects |
Within XpertRule Knowledge Builder, the developer can create custom procedures and command blocks to perform runtime procedural tasks.
Procedure code is written in the JavaScript language.
For those familiar with JavaScript, the only addition is that of a dictionary lookup identifier which allows (knowledge base) objects to be referenced more intuitively.
For readers more accustomed to working with the XpertRule commands a mapping has been provided to help in the transition.
XpertRule Commands
@ASSIGN Grade = 'Director'
XpertRule JavaScript
#Grade.val("Director");Notes
#Grade : This shortcut is translated into JavaScript code which retrieves the "Grade" object from the dictionary.
.val(<value>) : This method of the dictionary object (in this case the "Grade" object) sets its value.
@IF ( Grade = 'Director' )XpertRule JavaScript
if ( #Grade.val() == "Director" )Notes
.val() : If no parameter is passed to the val method, it returns the current value of the dictionary object.
TipsIn JavaScript there is a difference between using the equals sign as a comparator and an assignment. e.g.
if ( a == 57 )Check to see whether a is equal to 57
a = 57Assigns the value of a to be 57
The comparator for an "if" statement MUST be contained in brackets
@DEBUG 'Hello World'Standard JavaScript
alert("Hello World");XpertRule JavaScript
xpertrule.message('Hello World');Notes
xpertrule : The "xpertrule" object contains a number of helpful methods to enable the developer to achieve specific functionality which traditionally came from @commands.
.message(<contents>[,<title>]) : Display a message. An optional second parameter can be used to change the title of the message box.
@DO ExpensesXpertRule JavaScript
#Expenses.run();Notes
.run() : Execute an XpertRule object. This could be a tree, a procedure, a dialog etc.
TipsAs "run" is a method, the open and close brackets are required.
Procedures are called in the same was as any other Knowledge Builder object. e.g.
#MyProcedure.run();Values can be returned from a procedure with the JavaScript return statement. e.g.
MyProcedure definition
return 42;Calling procedure
var retVal = #MyProcedure.run();
@IF Grade = 'Director'XpertRule JavaScript
@ASSIGN Department = 'Boardroom'
@DEBUG 'Boardroom location'
@ELSEIF Grade = 'Senior Manager'
@ASSIGN Department = 'Management'
@DEBUG 'Management office'
@ELSE
@ASSIGN Department = 'Office'
@DEBUG 'General office'
@ENDIF
if (#Grade == "Director") {Notes
#Department.val("Boardroom");
xpertrule.message("Boardroom location");
} else if (#Grade == "Senior Manager") {
#Department.val("Management");
xpertrule.message("Management office");
} else {
#Department.val("Office");
xpertrule.message("General office");
}
Command blocks in JavaScript are denoted by open and close braces {}
Again, note the use of the double equals sign == to test equality
@DIM loop:nXpertRule JavaScript
@FOR loop = 1 TO 10
@ASSIGN strArr[loop] = 'Empty'
@NEXT
var loop;
for ( loop = 1 ; loop <= 10 ; loop = loop + 1 ) {
#strArr.val()[loop] = "Empty" ;
}
Alternatively, a more optimized version...
for ( var loop = 1 ; loop <= 10 ; loop++ )Notes
#strArr.val()[loop] = "Empty" ;
If there is only a single command in the command block, the braces {} are not required.
To increment a number, you can use the ++ syntax (there's also -- for decrement)
@Clear GradeXpertRule JavaScript
#Grade.clear();Tips
As with the run method, note the () after the method name.
@IF ( Grade.isempty )XpertRule JavaScript
if ( #Grade.isEmpty() )Tips
JavaScript is CaSe SeNsItIvE. XpertRule JavaScript methods names are in "Lower Camel Case". So the isEmpty method name has a lower case initial "i" and an upper case "E" as it's a separate word.
@DIM aName:sXpertRule JavaScript
var aName;Tips
JavaScript is a type-less language so there is no need to specify that the aName local variable is a string.
@DIM aName:sXpertRule JavaScript
@ASSIGN aName = 'Grade'
@ASSIGN !(aName) = 'Director'
var aName = "Grade";Notes
dictionary.findObject(aName).val("Director");
We define a local variable called "aName" (note the trailing semicolon)
dictionary : The "dictionary" object allows the developer to access the knowledge module's dictionary of objects
findObject(<object name>) : Get a reference to specified dictionary object. Note that this is quite an expensive (in terms of processing time) operation. If the same referenced object is accessed more than once in the code, it is preferable to store the object in a local variable. e.g.
var aObject = dictionary.findObject("Grade");
if ( aObject.isEmpty() )
aObject.val("Director");
@ENCODEDATAXML aStrXpertRule JavaScript
#aStr.val(xpertrule.encodeData());Notes
encodeData([<object array>[,<add captured attributes>]]) : Encode the relevant objects into an XML message (string) and return that string.
If you wish to specify specific objects to include in the message, you specify them as an OBJECT ARRAY as the first parameter. e.g.
xpertrule.encodeData([#Grade,#Department])
Note that an array is passed by using the square brackets, also, objects are passed (not names).
You could alternatively use the dictionary.findObject method to look up objects to pass although this would be slower e.g.
xpertrule.encodeData([dictionary.findObject("Grade"),dictionary.findObject("Department")])
If you need to include all the captured objects in addition to the specified objects, you can pass "true" as the second parameter e.g.
xpertrule.encodeData([#Grade,#Department],true)
@URLFETCH 'http://localhost/temp/temp.php',retStrXpertRule JavaScript
var dataObj = xpertrule.urlFetch('http://localhost/temp/temp.php');Notes
The urlFetch method returns a JavaScript object. This object has 2 properties...
data : The data returned from the HTTP request
success : A boolean indicating whether the request was successful
Once the call is complete, you can use the retuned object's properties thus...
var dataObj = xpertrule.urlFetch('http://localhost/temp/temp.php');
if (dataObj.success)
xpertrule.message(dataObj.data);
else
xpertrule.message("Error");
@IF Grade.description = ''XpertRule JavaScript
@ASSIGN Grade.description = 'Boss Type'
@ENDIF
if (#Grade.props.description == "")
#Grade.props.description == "Boss Type";
alternatively
if (#Grade.prop("description") == '')Notes
#Grade.prop("description","Boss Type");
The first snippet uses the props object to access the object control properties. This should be quite self-explanatory.
You'll see that the second snippet uses the prop method. This can be called with 1 or 2 parameters...
.prop(<object control property name>) Get the value of the specified object control property
.prop(<object control property name>, <new value>) Set the value of the specified object control property to the new value.
n.b. If setting a new value (either via the props object or the prop method), the TYPE of the new value must be the same as the XpertRule object control property type. e.g.
Set a string type property: .prop("help", "Foo Bar")
Set a numeric type property: .prop("minvalue", 22)
Set a boolean type property: .prop("allowblank", true)
Get the number of object instance properties...
XpertRule Commands@IF Grade.nValues = 1XpertRule JavaScript
if (#Grade.nValues == 1)
You can also retrieve the array of object instances via the value function...
var valArr = #Grade.value();
So an alternative way of getting the number of object instance properties would be...
if (#Grade.values().length == 1)
Or get an individual value...
var dirVal = #Grade.value(1)
n.b. The object returned from the value function (or array of objects if no parameter passed) are instances of the following object...
{Example. If the display text of the FIRST instance value's runtime text is empty then set it to a value
XpertRule JavaScriptif (#Grade.inst("displaytext",1) == '')
#Grade.inst("displaytext",1,"Big Boss Person");
Or, get the instance property value of the CURRENT selected value...
xpertrule.message(#Grade.inst("displaytext"));Notes
You'll see that the inst method can be called with 1, 2 or 3 parameters...
.inst(<object instance property name>) Get the value of the specified object instance property for CURRENT value instance
.inst(<object instance property name>, <instance index>) Get the value of the specified object instance property for specified instance
.inst(<object instance property name>, <instance index>, <new value>) Set the value of the specified instance control property for specified instance to the new value. Specifying an <instance index> or 0 sets the property on the currently selected value.
n.b. If setting a new value, the TYPE of the new value must be the same as the XpertRule object instance property type. (see Object Control Properties for more details)
The existing methods to modify the object instances are also supported in JavaScript
XpertRule Commands@DO Grade.ClearInstances @DO Grade.AddInstance('Big Boss') @DO Grade.DelInstance(4)XpertRule JavaScript
#Grade.clearInstances(); #Grade.addInstance("Big Boss"); #Grade.delInstance(4);
#Grade.addInstance("Big Boss", {DisplayName: "Big Boss Person"});If supplies, the javascript object is used to populate the instance properties of the newly added value. The above example assumes that the Grade object has an instance property called DisplayName of type string.
#Grade.addInstance("Big Boss", {DisplayName: "Big Boss Person", Age: 45});
With the use of the new OnShow dialog event, you can achieve some cool extras in your UI design.
The OnShow procedure is called once the dialog controls have been created for the first time. At this point you can retrieve a jQuery reference to any control on your dialog with the following selector (from an XpertRule procedure)...
var el = $("#myControlName");
The # means "find the element by id" and as the element ID is the same as the control name, you can find any of your controls.
If you wish to use a dialog element for your own use, it's a good idea to use a label control with the caption set to "__EMPTY__". This instructs the engine to NOT populate the control with the specified text (as the population of controls happens periodically from AFTER the OnShow event).
If the label caption is set to "__EMPTY__" then you can manually set the control's contents via the jQuery "html" method. So to extend our previous code...
var el = $("#myControlName");
el.html("This is <a>some text set via jQuery</a>");
We can also do cool stuff like animate the showing of the controls...
el.hide(); // start with the control hidden
el.show("slow"); // show the control "slowly"
Additional ideas...
Scroll controls onto the dialog (with the jQuery animate method)...
el.css('left','-100px').animate({left: '100'}, 2000);
The full jQuery reference can be found on the jQuery web site