ExternalType stereotype JavaScriptObject

With EGL, your Rich UI application can access non-generated JavaScript™. You might be making general logic available—for example, to provide a random number generator—or you might be referencing a non-EGL widget—for example, to allow use of a Dojo widget inside your code.

In either case, your tasks are twofold:

  1. To develop an EGL external type that makes the JavaScript logic available to a Rich UI application. The JavaScript is said to be the implementation of the external type.
  2. To write a non-generated JavaScript class, unless the external type references a built-in JavaScript class such as Math or Number.
If your external type is implemented by a JavaScript source file, the next statements apply:

If your external type is implemented by a built-in JavaScript class, do not set the relativePath property of the external type.

Regardless of how you implement the external type, if the name of the JavaScript class is different from the name of the external type, you must set the javaScriptName property to the name of the class.

To avoid errors at run time, avoid using multiple versions of the same runtime library in a given Rich UI application.

This topic describes the use of egl.defineClass. For details about defining a new widget, see “Extending the Rich UI widget set.”

Structure of general-use JavaScript code

If you are making general logic available—for example, a random number generator—place your JavaScript file in a subdirectory of the WebContent folder. The file invokes the egl.defineClass JavaScript function:
egl.defineClass(
   'packageName', 'className',
   'superclassPackageName', superclassName,
    {
      "constructor": function() 
      { },

      "otherFunction": function(parameterList)
      { }
    }
);
The parameters are as follows:
packageName
The name of the package in which the custom JavaScript resides. The package name is required, is case sensitive, and identifies the WebContent subfolder. Include dots in place of a forward slash for every subfolder under the first. For example, if your JavaScript is in the WebContent/myPkg/test folder, the packageName value is myPkg.test.
className
An identifier that you are assigning as the JavaScript class name. The class is a predefined collection of functions. The name must be the name of the EGL external type JavaScriptName property, which defaults to the name of the external type. The class name is case sensitive and is required.
superclassPackageName
Optional. The name of the package in which the EGL external type for a super class resides. The package name is case sensitive. If you specify this value, you must also specify the superclassName value.
superclassName
Optional. The name of a super class, which is also the name of an EGL external type that makes the superclass available to EGL source code. The superclass name is case sensitive. If you specify this value, you must also specify superclassPackageName value.
otherFunction
A function that is in addition to the one named "constructor," which is described later. You can specify any number of additional functions.
parameterList
A list of function parameters

The function named "constructor" is optional and, if present, runs as soon as you declare an EGL variable of the external type. That function cannot have parameters and can be in any position in the list of functions.

You can define multiple classes in a single JavaScript file, but the convention is to include only one class, with the same name as the file. For example, here is the code in the RandomNumberGenerator.js file, which makes available a random number generator:
egl.defineClass(
   'randomNumber', 'RandomNumberGenerator',	

   {	
	     "constructor" : function()
      {
         this.upperLimit = 100;
      },

      "setUpperLimit" : function(limit)
      {
         this.upperLimit = limit;
      },

      "getUpperLimit" : function()
      {
         return this.upperLimit;
      },

      "generateRandomNumber" : function()
      {
         return Math.floor(Math.random()*this.upperLimit);
      }
   }
);

The external type stereotype

In relation to JavaScript, the EGL External type stereotype is JavaScriptObject, as shown in the following example:
package client;

ExternalType RandomNumberGenerator type JavaScriptObject
   {
      relativePath = "randomnumber",
      externalName = "RandomNumberGenerator"
   }

   upperLimit int {@Property{getMethod = "getUpperLimit", 
                             setMethod = "setUpperLimit"}};
  
   function generateRandomNumber() returns(int);
end
The external type can include the extends clause, to reference an external type that represents a super class, as in the following example outline:
ExternalType MyType extends OtherType type JavaScriptObject

end
The external type also can include the following type-level properties, each of which takes a string:
relativePath
The location of the JavaScript file in relation to the WebContent folder. The property setting is optional. If the JavaScript file is stored directly in the WebContent folder and not in a subfolder, set the relativePath property to an empty string. In any case, do not include a file name in the property value.

When the external type is implemented by a JavaScript file, you must set the relativePath property. When the external type is implemented by a built-in class, do not set the property.

externalName
Specifies the name of the JavaScript class. Do not specify the file extension .js, which is assumed.

The property setting is optional. If you do not specify a value, the name of the JavaScript class is assumed to be the name of the external type.

You might use the externalName property to access a JavaScript class for which the name is an EGL reserved word. For example, the following external type makes possible the access of a JavaScript class named add, which is in the WebContent/part1/part2/add.js file:
ExternalType SumType type JavaScriptObject 
                          {relativePath = "part1/part2", externalName = "add" }
    ;
end
includeFile
Identifies an HTML file or other CSS or JavaScript files that are made available at run time. The path specified in includeFile is relative to the WebContent directory. An example is "JS/myFile.js".
The following file might be used if you were using the external type to reference a Dojo widget:
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js">
</script>

<style type="text/css">
   @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/dijit.css";
   @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
   @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
</style>
        
<script>
   dojo.require("dijit.form.Button");
   dojo.require("dijit.form.Slider");
</script>

That file loads the Dojo widget library and Dojo CSS files and starts the Dojo run time.

As shown in the example of an external type, a field in that type can include the following field-level annotation:
Property
This annotation is required if you want to access, from your EGL code, a JavaScript global field (a field of the form this.myField). If you want to assign a value from your EGL code, the JavaScript must define the field in the function named "constructor". However, you can retrieve a value from the JavaScript field regardless of where the field is defined in the JavaScript.
In general, Property identifies JavaScript functions that get and set the JavaScript field value. You can use this property without specifying function names if the names of the functions are built with the word get or set followed by the variable name. For example, if the variable is UpperLimit and the JavaScript class includes functions named getUpperLimit() and setUpperLimit(), you only need to add the complex property, as in this example:
UpperLimit INT { @Property{} };
The fields in the Property are as follows:
getMethod
A string (enclosed in quotation marks) containing the name of the get method for the specified variable (do not include parentheses). The method has no parameters, and its return value has the same type as the field.
setMethod
A string (enclosed in quotation marks) containing the name of the set method for the specified variable (do not include parentheses). The method has one parameter that has the same type as the field. By convention the setMethod does not have a return value, but no error condition results if the method returns a value.

If you specify only one of the two property fields, EGL assumes that the unspecified function is not available. An error does not occur unless an expression causes invocation of the function that is assumed to be missing.

JavaScript field names are case sensitive, as is the field name in the external type.

Note: After you make any change to the JavaScript file, you must re-save the corresponding EGL external type and then refresh the Rich UI handler that uses the external type. The requirement is a consequence of the generator's use of Asynchronous Module Definition (AMD) technology, which improves runtime performance.

Relationship of EGL and JavaScript data types

Table 1. EGL and JavaScript data types
EGL type JavaScript type (case-sensitive)
STRING String
BOOLEAN Boolean
SMALLINT, INT, FLOAT, SMALLFLOAT Number
BIGINT, DECIMAL, MONEY, NUM egl.javascript.BigDecimal (as described in a later section)
DATE, TIME, TIMESTAMP Date

EGL arrays are passed to JavaScript as JavaScript arrays. If an EGL type (such as an array) is set to null, the JavaScript code receives a JavaScript null.

egl.javascript.BigDecimal

The supplied JavaScript class egl.javascript.BigDecimal can precisely represent numbers that have a very large number of digits. This class also has methods for performing mathematical operations with BigDecimals.

The native numeric type in JavaScript is the Number class, which is a floating-point representation of numbers. The class is imprecise and cannot represent many values. Rounding errors might occur when you do math with values of the Number class.

A BigDecimal object cannot be changed after it has been created. For example, to add two BigDecimal values, write the code as follows:
   var result = bigDecimal1.add( bigDecimal2 ); 
The result is lost if you write the code as follows:
   bigDecimal1.add( bigDecimal2 ); 
The egl.javascript.BigDecimal constructor takes one argument, which is a String that contains the wanted value for the BigDecimal. Numbers in String form must have at least one digit and cannot contain a blank. They can have a leading sign, can have a decimal point, and can be in exponential notation. Here are some valid arguments:
  • "0"
  • "12"
  • "-76"
  • "12.70"
  • "+0.003"
  • "17."
  • ".5"
  • "4E+9"
  • "0.73e-7"
Here are JavaScript methods that use objects of egl.javascript.BigDecimal (such objects are identified as bd, and Number objects are identified as n):
  • abs() returns the absolute value of the BigDecimal
  • add(bd) returns the sum of the current object and the argument.
  • compareTo(bd) returns -1 if the current object is less than the argument, 1 if the current object is greater than the argument, or 0 if they are equal.
  • divide(bd) returns the result of dividing the current object by the argument.
  • divideInteger(bd) returns the integer part of the result of dividing the current object by the argument.
  • equals(obj) returns true if the argument, which can be any object, is a BigDecimal with the same value and scale (number of decimal digits) as the current object. This method returns false if the argument is not a BigDecimal, or is a BigDecimal with a different value or scale. The obj parameter is any object.
  • max(bd) returns the current object or the argument, whichever is greater.
  • min(bd) returns the current object or the parameter, whichever is smaller.
  • movePointLeft(n) returns a BigDecimal that is equivalent to the current object (a Number), but with the decimal point shifted to the left by the specified number of positions.
  • movePointRight( n) returns a BigDecimal that is equivalent to the current object (a Number), but with the decimal point shifted to the right by the specified number of positions.
  • multiply(bd) returns the result of multiplying the current object by the argument.
  • negate() returns the negation of the current object.
  • pow(bd) returns the result of raising the current object to the specified power. The power must be in the range -999999999 through 999999999 and must have a decimal part of zero.
  • remainder(bd) divides the current object by the argument and returns the remainder.
  • setScale(n, mode) returns a BigDecimal with the given scale (number of decimal digits). The argument n is a Number, and the optional argument mode is a constant, as described later.
    If n is larger than the current scale, the method adds trailing zeros to the decimal part of the number. If n is smaller than the current scale, the method removes trailing digits from the decimal part of the number, and mode indicates how to round the remaining digits. Here are the possible values of mode:
    • The default (egl.javascript.BigDecimal.prototype.ROUND_UNNECESSARY) indicates that no rounding is necessary.
    • egl.javascript.BigDecimal.prototype.ROUND_CEILING causes rounding to a more positive number.
    • egl.javascript.BigDecimal.prototype.ROUND_DOWN causes rounding toward zero.
    • egl.javascript.BigDecimal.prototype.ROUND_FLOOR causes rounding to a more negative number.
    • egl.javascript.BigDecimal.prototype.ROUND_HALF_DOWN causes rounding to the nearest neighbor, where an equidistant value is rounded down.
    • egl.javascript.BigDecimal.prototype.ROUND_HALF_EVEN causes rounding to the nearest neighbor, where an equidistant value is rounded to the nearest even neighbor.
    • egl.javascript.BigDecimal.prototype.ROUND_HALF_UP causes rounding to the nearest neighbor, where an equidistant value is rounded up.
    • egl.javascript.BigDecimal.prototype.ROUND_UP causes rounding away from zero.

  • scale() returns the number of digits after the decimal point, as a Number.
  • signum() returns -1 if the number is negative, zero if the number is zero, and 1 if the number is positive.
  • subtract(bd) returns the result of subtracting the parameter from the current object.
  • toString() returns a String representation of the BigDecimal object.
The following constants are also defined by BigDecimal:
  • egl.javascript.BigDecimal.prototype.ZERO is BigDecimal with the value zero.
  • egl.javascript.BigDecimal.prototype.ONE is a BigDecimal with the value one.
  • egl.javascript.BigDecimal.prototype.TEN is a BigDecimal with the value ten.

JavaScriptObjectException

If a non-generated JavaScript function is invoked by way of an external type and if the function throws an error, the invocation causes an EGL JavaScriptObjectException. Like every EGL exception, the JavaScriptObjectException has message and messageID fields.

If a JavaScript error object is caught, the message field is set from the equivalent field of the error object. Otherwise, the message field receives a string that is equivalent to the value thrown by the JavaScript function.

Here is the additional field in JavaScriptObjectException:
name
If a JavaScript error object is caught, the name field is set from the equivalent field of the error object. Otherwise, the name field receives an empty string.