Nexacro Platform Script Language

Scripts used for developing applications on Nexacro Platform have been developed based on the scripts used in HTML5 specifications. As a result, web developers can create Nexacro Platform scripts without learning a new script language.

However, HTML5 specs are continuously being developed, and scripts supported by the Nexacro Platform are also provided to support functionalities needed by enterprise users. Consequently, you should become familiar with the basic HTML5 and Nexacro Platform script languages to develop optimal applications.

Scope

Scope explains issues related to the range of accessible variables. Applications used in business often manipulate a number of screens simultaneously and refer to a variable in multi-screens. Understanding the scope, you can know how to get access to associated resources.

this

When designating the effective scope for items used in ADL or the application form, you always need to use "this". You should designate a proper level of scope when referring to properties and forms, as well as variables.

Variables within the form are declared as follows:

this.formvalue = 4;

Even when a function is declared, you need to designate the scope. When referring to a declared variable within the form, you need to designate the scope.

this.formvalue = 4;

this.test = function()
{
     this.formvalue = 3;
     this.parent.value = 3;
     this.parent.parent.value = 3;
}

In case of methods, such as trace or alert, other methods are executed according to the designated scope. Using alert() and this.alert() are different in the sense that they use different methods.

this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
     alert(e.button);
     this.alert(e.button);
}

But variables declared within a function may be used without designating the scope separately. The value delivered through parameters can also be used without designating the scope.

this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
     obj.set_text("button");
     var a = 3;
     trace(a); // 3
}

When declaring a function, you need to designate the scope so that it can be included as a member of a form or an application.

this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
...
}

When using the eval function to access a form, this should be used as well.

eval("this.formfunc()");

The best practice is to declare a function directly even though you could do it as in the previous version because it is processed globally and cannot be supported later on.


function Button00_onclick(obj:Button, e:nexacro.ClickEventInfo)

{

...

}

Global

All variables or functions with scope not designated within the Nexacro Platform script will be treated as top-level global members.

Moreover, all scripts without designated scope, as shown in the below example, will be treated as global. Scripts will be also treated as global when the keyword var is used outside a function.

globalvar = 2; 
var globalvar2 = 3;

Even variables used in a function are treated as global when their scopes are not designated. However, variables defined by using the keyword var cannot be used outside a function.

this.test = function()
{
	trace(globalvar); //2
	trace(globalvar2); //3
	
	value = 4;
	var localvar = 5;
}


this.test = function()
{
	trace(value); // 4
	trace(localvar); // ReferenceError: localvar is not defined
}

When a form includes a script file from outside, it will treat the script file as a function. Therefore, you should be careful when using the keyword var.


Please see the below two sample codes. Code 2 (includecode.xjs.js) shows how the variables defined in the includecode.xjs file are processed after generation. (The generated code may differ according to the version of the platform.)

$r_title(includecode.xjs)
bbb = "bbb";
var ccc = "ccc";
$r_title(includecode.xjs.js)
(function()
{
	return function(path)
	{
		var obj;

		// User Script
		this.registerScript(path, function() {
			bbb = "bbb";
			var ccc = "ccc";
		});

		this.loadIncludeScript(path);
		obj = null;
	};
}
)();

When you declare or call a function, you need to designate the associated scope. Test() and this.test() in the script below calls two different functions respectively. If you call test() without designating the scope, the function declared in global will be called.

this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
     test();
     this.test();
}

The functions designated without the scope shown as below will be treated as global.

Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo)
{
...
}

function Button00_onclick(obj:Button, e:nexacro.ClickEventInfo)
{
...
}

You can use methods such as Alert(), Confirm(), or Trace() as Global. If you want to use the form methods as you did in the previous version, you should designate the scope with this.

For applications or form methods such as dialog(), open(), exit(), or transaction(), you should designate the applicable scope.


//application

application.open("");

application.exit("");

application.transaction("");


//Form

this.close("");

this.go("");


//ADL

this.open("");

this.exit("");

this.transaction("");

The best practice is to specify variables to be utilized for the entire application by registering them as application variables instead of global variables.

Expr

The expr script can be used without designating the scope as it is processed based on an internally bound dataset within Nexacro Platform. However, you should designate the scope to access an unbound dataset directly.

To use expr in a bound dataset shown, you do not need to use this as shown here.

<Cell text="expr:Column00"/>
<Cell text="expr:Column00.min"/>
<Cell text="expr:currow"/>
<Cell text="expr:rowposition"/>
<Cell text="expr:getSumNF('col0')"/>
Dataset.set_filterstr("Column00=='test'");
Dataset.filter("Column00=='test'");

When you designate bound grids, datasets and cells, the following indicators should be used.

Grid: comp
dataset: dataset
Cell: this
<Cell text="expr:this.col"/> <!-- cell -->
<Cell text="expr:dataset.rowcount"/> <!-- binded dataset -->
<Cell text="expr:comp.currentcell"/> <!-- grid -->
<Cell text="expr:dataset.parent.func1()"/> <!-- form -->
<Cell text="expr:comp.parent.func1()"/> <!-- form -->

There are no specific indicators for forms, so you can use comp.parent or dataset.parent if necessary.

If you use this instead of comp.parent.func() when you access a function in a form, it will be processed as an error. In an expr script, this means cell.

<Cell text="expr:this.func01()"/>

If a component has expr and text as its property at the same time, the displaytext property, which returns the text displayed on the screen, can be used.

this.Button00.set_text("text");
this.Button00.set_expr("1+1");

trace(this.Button00.text); // "text"
trace(this.Button00.expr); // "1+1"
trace(this.Button00.displaytext); // "2"

lookup

The lookup method is designed to be used when it is difficult to access with the designated scope. For example, you can look up objects or functions with ID names or function names.

The lookup method is used in the actual code as follows.

Form.lookup( strid );
Frame.lookup( strid );
Application.lookup( strid );
EventSyncObject.addEventHandlerLookup( eventid, funcid, target );

Here are additional examples.

// it returns an object relevant to objectid after lookup in this
var obj = this.lookup("objectid");

// it returns a function relevant to fn_onclick after lookup in this
this.lookup("fn_onclick")();

// Event handler handles a function relevant to fn_onclick after lookup in this
btn00.addEventHandlerLookup( "onclick", "fn_onclick", this );

Event Handler

Event handlers to deal with events can be added in the Properties window when using Nexacro Studio, or they can be added within scripts by using methods provided for each component and object as described in this section.

Method

Methods to add/set/delete event handlers are provided in order to handle events within scripts:

Use appropriate methods to process events according to the scope of functions.

this.btn00.setEventHandler("onclick", this.fn_onclick, this);
this.dataset00.addEventHandlerLookup("onrowposchange", "fn_onchange", this);

Because methods such as addEventHandlerLookup, setEventHandlerLookup, and removeEventHandlerLookup may affect performance of applications, it is recommended you use them only when necessary.

When you create an event using the properties window, the event is written as a character string as follows.

<Button id="Button00" ... onclick="Button00_onclick"/>

The relevant code will be used as attached with an indicator this in the generated JavaScript code after the build.

this.Button00.addEventHandler("onclick", this.Button00_onclick, this);

The addHandler, setHandler, and removeHandler methods provided in the previous version are no longer supported.

The Btn00.onclick.addHandler(button00_onclick) form is not supported anymore.

Type

You can set the object type when you set arguments to the event handler functions. Type is provided internally on Nexacro Studio for development convenience, which is not the JavaScript's standard grammar.

this.Button00_onclick = function(obj:Button,  e:nexacro.ClickEventInfo)
{
	trace(obj.text);
}

Based on the input type value, Nexacro Studio supports the code hint function.

When you convert the relevant code to JavaScript code, delete the type value.

this.Button00_onclick = function(obj,  e)
{
	trace(obj.text);
}

Even though you do not designate the object type, it does not have any effect on executing the application.

The object type is not supported in other functions except the event handler function, where it can have an effect on the application's action.

Setter

You can process the access restrictions of variables by using Setter/Getterfrom from ECMAScript 5. But they are not supported on Internet Explorer 8 or earlier. For that reason, Nexacro Platform provides a special set method.

Set Method

You can apply the text property to a button component as follows.

this.Button00.set_text("text");
trace(this.Button00.text);

The following method directly accessing the property value is no longer supported.


Button00.text = "text";

You can access object properties added directly as you done in the previous version.


<Button myprop="333">

Button00.myprop = "333";

Button00.mytext = "text";

You can access the style properties by using the set method. The added set method includes subordinate properties. The existing properties are available only when fetching the values.

this.Button00.style.set_color('aqua');
trace(this.Button00.style.color); // 'aqua'

If you try to get the style property values before calling the set method, they might return "null".

The CSS code is identical to the existing code.

Button
{
     background : red;
}

When you use ActiveX (plug-in) or the applet component, you can specify properties or call methods as follows.


this.ActiveX00.setProperty("prop1", 3 );

var v = this.ActiveX00.getProperty("prop1");


this.ActiveX00.callMethod("method1", arg1, arg2 );

var v = this.ActiveX00.callMethod("method2");

Dynamic Properties

You can import property values using the existing method, but in case of objects whose property values change dynamically, a special get method is provided. For four properties in system objects - CursorX, CursorY, ScreenWidth, and ScreenHeight - you should use these additional methods:

System.getCursorX();
System.getCursorY();
System.getScreenWidth();
System.getScreenHeight();

Depending on component types, some properties which are not used cannot be adjusted. For example, if the calendar component type is not spin, you cannot adjust the properties below.

this.Calendar.spindownbutton
this.Calendar.spinupbutton

In the calendar component, the spindownbutton property refers the control property, and the property itself is output as a character string [object ButtonControl].

Other Changes and Restrictions

Nexacro Methods

Nexacro Platform used to support methods not supported by ECMAScript, but the methods are no longer supported because Nexacro Platform has been changed. Instead, they are separately provided as Nexacro methods.

For example, the floor, ceil and round methods that supported two parameters in the math object are no longer available. If you want to use any of these methods, you must use the corresponding Nexacro methods.

//Math.floor( v, digit );
nexacro.floor( v, digit );

//Math.ceil( v, digit );
nexacro.ceil( v, digit );

//Math.round( v, digit );
nexacro.round( v, digit );

Some of object names used as reserved words in JavaScript have been changed.

//new Image();
new nexacro.Image();

Other component class names in TypeDefinition (not duplicated with reserved words) have been changed, such as nexacro.Button. However, you can use the button in the same way you did before.

this.button00 = new Button();
or
this.button00 = new nexacro.Button();

Some of the properties and objects have been changed as they collide with reserved words.


Component.class → Component.cssclass

Export.export() → Export.exportData()

Buffer.delete() → Buffer.remove()

VirtualFile.delete() → VirtualFile.remove()

Operational Mode Change

Some of the items previously not supported by JavaScript, or working differently, have been changed.

<> Comparison operator not supported

<> Comparison operator is no longer supported. If you want to compare other values, use the operator "!=".

Character string processing method change within the switch statement

In the previous version, case "2" and case 2 were processed in the same way within the switch statement. In the present version, these are treated as different values.

Regular expression /g option applying method change

If you apply “replace” to the regular expression instead of the /g option, only one item will be changed. You need to apply the /g option to change entire items.

Restrictions on Object Names

You cannot create a ChildName identical to names of methods/properties or the container members. For example, you cannot designate a button component's ID as "text" since a form has the text property. The button cannot be created in the following case.

<Form text="formtext">
     <Layouts>
          <Layout>               
               <Button id="text'>

For invisible objects such as datasets you cannot designate their IDs as property names, such as length, since they are treated as array members. In the following example, the columns cannot be created.

<Objects>
     <Dataset id="Dataset00">
          <ColumnInfo>
               <Column id="length" type="STRING" size="256"/>
          </ColumnInfo>

Restrictions on Variable or Function Names

If a variable or function includes an underbar (_) at the beginning its name, it can collide with the variables or functions registered in the Nexacro Platform libraries. The collision can result in the failure to load the application or cause the application to behave differently from your intention.

For example, the below script will fail to be loaded, and thus nothing will appear on the screen. The reason is that a variable is declared with the name _is_loading, which equals the name of a variable in the Nexacro Platform libraries.

this._is_loading = true;
this.Button00_onclick = function(obj:Button,  e:nexacro.ClickEventInfo)
{
	trace(this._is_loading);
}

Even if a variable or function does not include an underbar (_) in its name, it can collide with the variables or functions registered in the Nexacro Platform libraries.

For example, the below script will fail to create a component, and thus nothing will appear on the screen. The reason is that a function is declared with the name createComponent, which equals the name of a function in the Nexacro Platform libraries.

this.createComponent = function()
{
	trace('createComponent ');
}