넥사크로플랫폼에서 애플리케이션 개발 시 사용하는 스크립트는 HTML5 명세서에서 사용하는 스크립트를 기준으로 개발됐습니다. 따라서 기존 웹 개발자가 별도로 스크립트 언어를 익히지 않아도 넥사크로플랫폼 스크립트를 작성할 수 있습니다.
하지만 HTML5은 계속 개발되고 있으며 아직 제공되지 않지만, 기업 내에서 필요한 기능을 지원하기 위해 넥사크로플랫폼 자체적으로 지원하는 스크립트도 같이 제공됩니다. 그래서 최적의 성능을 내는 애플리케이션을 만들기 위해서는 기본적인 스크립트 언어와 함께 넥사크로플랫폼 스크립트 언어에 대한 기본적인 지식이 필요합니다.
이번 장에서는 기존 버전에서 변경된 스크립트 언어를 설명합니다.
유효범위(Scope)
유효범위는 접근 가능한 변수의 범위와 관련된 내용을 설명합니다. 유효범위 또는 영역이라고 표기하며 영문 표기 그대로 사용할 때도 많습니다. 업무에 사용하는 애플리케이션은 여러 개의 화면을 동시에 조작하고 하나의 변수를 여러 화면에서 참조하는 경우가 많은데 이러면 어떤 식으로 원하는 자원에 접근할 수 있는지 유효범위를 통해 알 수 있습니다.
this
ADL 또는 폼에서 사용되는 항목에 대해 유효범위를 지정할 때는 항상 this를 사용합니다. 변수뿐 아니라 속성, 폼 간의 참조 시에도 적절한 유효범위를 지정해주어야 합니다.
폼 내에서 변수는 아래와 같이 선언합니다.
this.formvalue = 4;
함수를 선언할 때도 유효범위를 지정해주어야 합니다. 또한, 함수 내에서 폼 내에 선언된 변수를 참조할 때도 유효범위를 지정해주어야 합니다.
this.formvalue = 4; this.test = function() { this.formvalue = 3; this.parent.value = 3; this.parent.parent.value = 3; }
trace나 alert과 같은 메소드는 지정된 유효범위에 따라 다른 메소드가 실행됩니다. alert()만 사용하는 것과 this.alret()을 사용하는 것은 서로 별개의 메소드를 실행하는 것입니다.
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { alert(e.button); this.alert(e.button); }
단 함수 내에서 선언된 변수는 유효범위를 따로 지정하지 않고 사용할 수 있으며 매개변수로 전달된 값 역시 유효범위를 지정하지 않고 사용할 수 있습니다.
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { obj.set_text("button"); var a = 3; trace(a); // 3 }
함수 선언 시에도 유효범위를 지정해 해당하는 애플리케이션 또는 폼의 멤버로 포함되도록 합니다.
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { ... }
eval 함수로 폼을 접근하는 경우에도 this를 사용해야 합니다.
eval("this.formfunc()");
이전 버전에서 사용하던 것처럼 함수를 직접 선언할 수도 있지만, Global로 처리되며 이후 지원이 중단될 수 있으므로 권장하지 않습니다.
function Button00_onclick(obj:Button, e:nexacro.ClickEventInfo)
{
...
}
Global
넥사크로플랫폼 스크립트 내에서 유효범위를 지정하지 않은 변수나 함수는 모두 최상위 Global 멤버로 처리됩니다.
아래와 같이 유효범위를 지정하지 않고 사용된 스크립트는 모두 Global로 처리됩니다. 함수 밖에서 var 키워드를 사용하는 경우에도 Global로 처리됩니다.
globalvar = 2; var globalvar2 = 3;
함수 내에 사용된 변수라도 유효범위를 지정하지 않으면 모두 Global로 처리됩니다. 단 var 키워드를 사용해 정의한 변수는 함수 밖에서 사용할 수 없습니다.
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 }
Form 내에서 다른 스크립트 파일을 include 하는 경우에는 내부적으로 스크립트를 함수로 처리합니다. 때문에 var 키워드를 사용할 때 주의해야 합니다.
예를 들어 includecode.xjs 파일 내 정의된 변수가 실제 generate 된 includecode.xjs.js 코드는 아래와 같습니다 (generate 된 코드는 버전에 따라 달라질 수 있습니다).
$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; }; } )();
함수를 선언하거나 호출할 때도 유효범위를 지정해주어야 합니다. 아래 스크립트에서 test()와 this.test()는 서로 다른 함수를 호출합니다. 유효범위를 지정하지 않고 test()를 호출하게 되면 Global에 선언된 test 함수를 호출합니다.
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { test(); this.test(); }
아래와 같이 유효범위 없이 지정된 함수는 Global로 처리됩니다.
Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { ... } function Button00_onclick(obj:Button, e:nexacro.ClickEventInfo) { ... }
Alert(), Confirm(), Trace() 메소드를 Global로 사용할 수 있습니다. 이전 버전처럼 폼 메소드로 사용하려면 this 로 유효범위를 지정해주어야 합니다.
dialog(), open(), exit(), transaction() 과 같은 애플리케이션 또는 폼 메소드는 해당하는 유효범위를 지정해주어야 합니다.
//application
application.open("");
application.exit("");
application.transaction("");
//Form
this.close("");
this.go("");
//ADL
this.open("");
this.exit("");
this.transaction("");
애플리케이션 전체에서 사용하고 싶은 변수는 Global 변수가 아닌 애플리케이션 변수로 등록해서 사용하는 것을 권장합니다.
Expr
expr 스크립트는 넥사크로플랫폼 내부적으로 바인딩 된 Dataset을 기준으로 처리되기 때문에 별도의 유효범위를 지정하지 않아도 사용할 수 있습니다. 단 바인딩 되지 않은 Dataset에 직접 접근하려면 유효범위를 지정해주어야 합니다.
아래와 같이 바인딩 된 Dataset에 대해 expr를 사용하는 경우에는 this를 붙이지 않습니다.
<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'");
바인딩 된 Grid, Dataset, Cell을 지정하는 경우에는 아래와 같은 지시자를 사용합니다.
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 -->
form에 대한 지시자를 별도로 제공하지 않으며 필요하면 comp.parent 또는 dataset.parent 와 같이 접근합니다.
폼 내에 있는 함수에 접근할 때 comp.parent.func() 형식을 사용하지 않고 this를 사용하게 되면 오류로 처리됩니다. expr 스크립트에서 this는 cell을 가리킵니다.
<Cell text="expr:this.func01()"/>
컴포넌트 속성으로 Expr과 Text가 같이 있는 경우에 화면에 보이는 텍스트를 반환하는 displaytext 속성을 사용할 수 있습니다.
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
lookup 메소드는 유효범위를 지정해 접근하기 어려운 경우 사용할 수 있도록 설계된 추가 메소드입니다. 원하는 오브젝트나 함수를 id 또는 함수명을 가지고 찾을 수 있습니다.
lookup 메소드는 아래와 같은 형식으로 사용할 수 있습니다.
Form.lookup( strid ); Frame.lookup( strid ); Application.lookup( strid ); EventSyncObject.addEventHandlerLookup( eventid, funcid, target );
실제 코드에서는 아래와 같이 사용됩니다.
// this에서 상위로 검색해서 objectid에 해당하는 오브젝트를 반환 var obj = this.lookup("objectid"); // this에서 상위로 검색해서 fn_onclick에 해당하는 함수를 반환 this.lookup("fn_onclick")(); // this에서 상위로 검색해서 fn_onclick에 해당하는 함수를 이벤트 핸들러에서 처리 btn00.addEventHandlerLookup( "onclick", "fn_onclick", this );
이벤트 핸들러
이벤트 처리를 위한 이벤트 핸들러는 넥사크로 스튜디오 속성창에서 추가하거나 각 컴포넌트, 오브젝트에 제공하는 메소드를 사용해 스크립트에서 추가할 수 있습니다.
메소드
스크립트 내에서 이벤트 처리를 위해 이벤트 핸들러를 추가, 설정하거나 삭제할 수 있는 메소드를 제공합니다. 기존 버전에서는 addHandler, setHandler, removeHandler 3개의 메소드를 제공했지만, 해당 메소드는 더는 지원하지 않습니다
addEventHandler( eventid, funcobj, target )
addEventHandlerLookup( eventid, funcstr, target )
setEventHandler( eventid, funcobj, target )
setEventHandlerLookup( eventid, functstr, target )
removeEventHandler( eventid, funcobj, target )
removeEventHandlerLookup( eventid, funcstr, target )
이벤트를 처리할 함수의 유효범위에 따라 적절한 메소드를 선택해 사용합니다.
this.btn00.setEventHandler("onclick", this.fn_onclick, this); this.dataset00.addEventHandlerLookup("onrowposchange", "fn_onchange", this);
addEventHandlerLookup, setEventHandlerLookup, removeEventHandlerLookup 메소드는 애플리케이션 성능에 영향을 미칠 수 있으므로 필요한 경우만 사용을 권장합니다.
btn00.onclick.addHandler(button00_onclick) 형식은 더는 지원하지 않습니다.
이벤트를 속성 창에서 생성하게 되면 아래와 같이 문자열로 설정됩니다.
<Button id="Button00" ... onclick="Button00_onclick"/>
해당 코드는 빌드 작업 후 변환된 자바스크립트 코드에서는 아래와 같이 this 지시자를 붙여서 생성됩니다.
this.Button00.addEventHandler("onclick", this.Button00_onclick, this);
타입
넥사크로 스튜디오에서 이벤트 핸들러 함수에 매개변수를 설정할 때 오브젝트의 타입을 지정할 수 있습니다. 타입은 자바스크립트 표준 문법은 아니며 넥사크로 스튜디오 내부에서 개발 편의성을 제공하기 위해 지원되는 형식입니다.
this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { trace(obj.text); }
입력된 타입 값을 기준으로 넥사크로 스튜디오에서 코드 힌트 기능을 지원합니다.
해당 코드를 자바스크립트 코드로 변환할 때는 타입 값을 제거합니다.
this.Button00_onclick = function(obj, e) { trace(obj.text); }
오브젝트 타입을 지정하지 않아도 애플리케이션이 실행하는데 영향을 미치지 않습니다.
이벤트 핸들러 함수 외 다른 함수에서는 오브젝트 타입을 지원하지 않으며 애플리케이션 동작에 영향을 미칠 수 있습니다.
Setter
ECMAScript 5부터는 Setter/Getter를 사용해 변수의 접근 제한을 처리할 수 있습니다. 하지만 IE8 이하 웹브라우저에서 지원할 수 없는 명세서이기 때문에 넥사크로플랫폼에서는 별도의 set 메소드를 제공합니다.
set 메소드
예를 들어 Button 컴포넌트의 text 속성을 사용할 때는 아래와 같이 사용할 수 있습니다.
this.Button00.set_text("text"); trace(this.Button00.text);
아래와 같이 속성값을 직접 접근하는 방식은 더는 지원하지 않습니다.
this.Button00.text = "text";
사용자가 직접 추가한 오브젝트 속성에 접근할 때는 기존처럼 접근할 수 있습니다.
<Button myprop="333">
this.Button00.myprop = "333";
this.Button00.mytext = "text";
스타일 속성에 접근하는 방식도 set 메소드를 사용해야 합니다. 추가된 set 메소드에는 하위 속성까지 포함하고 있습니다. 기존 속성은 값을 가져올 때만 사용할 수 있습니다.
this.Button00.style.set_color('aqua'); trace(this.Button00.style.color); // 'aqua'
set 메소드를 호출하기 전에 스타일 속성값을 가져오려하면 null 값이 나올 수 있습니다.
단, CSS 코드는 기존과 동일합니다.
Button { background : red; }
액티브X(플러그인)나 애플릿 컴포넌트를 사용할 때 속성을 지정하거나 메소드를 호출하는 방식도 아래와 같이 사용하게 됩니다.
this.ActiveX00.setProperty("prop1", 3 );
var v = this.ActiveX00.getProperty("prop1");
this.ActiveX00.callMethod("method1", arg1, arg2 );
var v = this.ActiveX00.callMethod("method2");
동적인 속성
속성값을 가져오는 것은 기존과 같지만 예외적으로 동적으로 속성값이 변경되는 오브젝트는 별도의 GetMethod를 제공합니다. System 오브젝트의 curx, cury, screenwidth, screenheight 4개 속성은 추가된 메소드를 사용해야 합니다.
System.getCursorX(); System.getCursorY(); System.getScreenWidth(); System.getScreenHeight();
컴포넌트 타입에 따라 사용하지 않는 속성은 접근할 수 없습니다. 예를 들어 Calendar 컴포넌트의 타입이 spin이 아닌 경우에는 아래 속성에 접근할 수 없습니다.
this.Calendar.spindownbutton this.Calendar.spinupbutton
Calendar 컴포넌트에서 spindownbutton 속성은 컨트롤 속성(Control Property)라고 하며 속성 자체를 문자열로 출력하면 [object ButtonControl]라고 표시됩니다.
기타 변경 및 참고 사항
nexacro 메소드
ECMAScript에서 지원하지 않는 메소드를 넥사크로플랫폼 자체적으로 추가해 사용하던 것을 표준에 따라 변경하면서 더는 지원하지 않습니다. 대신 해당 메소드는 nexacro 메소드로 별도 제공합니다.
예를 들어 Math 오브젝트에서 제공하던 메소드 중 2개의 인자를 지원하는 floor, ceil, round 메소드는 더는 제공되지 않습니다. 해당 메소드를 사용하려면 nexacro 메소드로 사용해야 합니다.
//Math.floor( v, digit ); nexacro.floor( v, digit ); //Math.ceil( v, digit ); nexacro.ceil( v, digit ); //Math.round( v, digit ); nexacro.round( v, digit );
또한, 자바스크립트에서 예약어로 사용하는 일부 오브젝트의 명칭이 변경되었습니다.
//new Image(); new nexacro.Image();
예약어와 중복되지 않는 나머지 컴포넌트도 TypeDefinition 내의 classname이 nexacro.Button과 같은 형식으로 변경되었습니다. 하지만 기존처럼 Button을 그대로 사용할 수 있습니다.
this.button00 = new Button(); or this.button00 = new nexacro.Button();
속성이나 오브젝트도 예약어와 충돌되어 일부 변경되었습니다.
Component.class → Component.cssclass
Export.export() → Export.exportData()
Buffer.delete() → Buffer.remove()
VirtualFile.delete() → VirtualFile.remove()
동작 방식 변경
자바스크립트에서 지원하지 않거나 다르게 동작하는 일부 항목이 수정되었습니다.
- <> 비교 연산자 지원하지 않음
<> 비교 연산자를 더는 지원하지 않습니다. 다른 값을 비교할 때는 != 연산자를 사용하세요.
- switch 문 내 문자열 처리 방식 변경
이전 버전에서는 switch 문 내에서 case "2" 와 case 2 가 같은 방식으로 처리되던 것을 별개의 값으로 처리합니다.
- 정규표현식 /g 옵션 적용 방식 변경
정규표현식에서 /g 옵션을 사용하지 않고 replace를 적용하게 되면 한 개의 항목만 변경되며 /g 옵션을 적용해야 전체 항목이 변경됩니다.
오브젝트 명 생성 시 제약 사항
컨테이너의 멤버인 속성, 메소드명과 같은 ChildName을 만들 수 없습니다. 예를 들어 폼은 text라는 속성이 있는데 추가된 버튼 컴포넌트의 id를 text로 지정할 수 없습니다. 아래 같은 경우 버튼이 생성되지 않습니다.
<Form text="formtext"> <Layouts> <Layout> <Button id="text'>
Dataset과 같은 Invisible 오브젝트 역시 Array의 멤버로 처리되어 length와 같은 속성을 id로 지정할 수 없습니다. 아래 같은 경우 컬럼이 생성되지 않습니다.
<Objects> <Dataset id="Dataset00"> <ColumnInfo> <Column id="length" type="STRING" size="256"/> </ColumnInfo>
변수, 함수 명 생성 시 제약 사항
변수명이나 함수명 앞에 언더바(_)를 포함하는 경우 넥사크로플랫폼 라이브러리에서 사용하는 변수나 함수와 충돌할 수 있습니다. 이로 인해 화면이 보이지 않거나 의도와 다른 방향으로 애플리케이션이 동작할 수 있습니다.
예를 들어 아래의 경우 로딩이 완료되지 않고 화면이 보이지 않습니다. 넥사크로플랫폼 라이브러리에서 사용하는 _is_loading 변수와 같은 이름으로 변수명을 만들었습니다.
this._is_loading = true; this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { trace(this._is_loading); }
언더바(_)를 포함하지 않더라도 넥사크로플랫폼 라이브러리에서 사용하는 일부 변수명이나 함수명과 충돌할 수 있습니다.
예를 들어 아래의 경우 컴포넌트 생성이 완료되지 않고 화면이 보이지 않습니다. 넥사크로플랫폼 라이브러리에서 사용하는 createComponent 함수와 같은 이름으로 함수명을 만들었습니다.
this.createComponent = function() { trace('createComponent '); }
Modeless 팝업창에서 application 오브젝트 사용 시 주의 사항
open 메소드로 실행한 Modeless 팝업창에서 application 오브젝트를 참조하는 경우 실행 성능에 영향을 미칠 수 있고 스크립트 에러가 발생할 수 있습니다.
HTML5 환경에서 실행 시 발생하는 문제이며 사용자 시스템과 브라우저 특성에 따라 발생하는 문제입니다. IE 브라우저와 같은 구형 브라우저 사용 시 현상이 두드러지게 나타날 수 있습니다.
특히, 아래와 같이 ADL 내 공통 스크립트 함수에서 showModal 메소드를 실행하도록 작성하고 Modeless 팝업창에서 해당 함수에 접근해 모달 팝업창을 생성하고 닫을 경우 참조 문제로 스크립트 에러가 발생할 수 있습니다. 사용자 시스템에 따라 발생할 수 있는 스크립트 에러는 달라지거나 중복 발생할 수 있습니다.
// ADL Script this.appModal = function(form) { newChild.showModal(form.getOwnerFrame(), null, form, "fn_callback"); } // Modeless popup window script this.Button00_onclick = function(obj:Button, e:nexacro.ClickEventInfo) { application.appModal(this); }