클라이언트 측 스크립팅 설계 및 처리
클라이언트 스크립트를 잘 디자인하면 사용자가 양식을 완성하는 데 걸리는 시간을 줄일 수 있습니다.
적절한 클라이언트 측 처리는 양식 로드에 따라 먼저 달라집니다. 양식 로드 전에 기록을 업데이트하면 클라이언트 측 처리를 우회하는 예기치 않은 결과가 발생할 수 있습니다.
- 테이블에 대한 목록 편집을 비활성화합니다.
- 목록 편집을 위한 적절한 비즈니스 규칙 또는 액세스 통제를 생성합니다.
- 데이터 정책을 생성합니다.
- 별도의 onCellEdit 클라이언트 스크립트를 만듭니다.
목록 편집 제한
양식의 필드에 대한 UI 정책 또는 클라이언트 스크립트를 만드는 경우 다른 방법을 사용하여 해당 필드의 데이터가 목록에서 유사하게 제어되도록 해야 합니다.
- 테이블에 대한 목록 편집을 비활성화합니다.
- 목록 편집을 위한 적절한 비즈니스 규칙 또는 액세스 통제를 생성합니다.
- 데이터 정책을 생성합니다.
- 별도의 onCellEdit 클라이언트 스크립트를 만듭니다.
서버 조회 최소화
클라이언트 데이터를 최대한 많이 사용하여 시간이 많이 걸리는 서버 조회의 필요성을 제거합니다.
클라이언트 스크립팅은 클라이언트에서 사용할 수 있는 데이터 또는 서버에서 검색된 데이터를 사용합니다. 서버에서 정보를 얻는 가장 좋은 방법은 g_scratchpad 및 비동기 GlideAjax 조회입니다.
이러한 방법의 주요 차이점은 양식이 로드될 때(정보가 서버에서 클라이언트로 푸시됨) g_scratchpad 한 번 전송되는 반면 GlideAjax는 클라이언트가 서버에서 정보를 요청할 때 동적으로 트리거된다는 것입니다.
g_scratchpad를 사용하여 서버 데이터 검색
g_scratchpad 개체는 클라이언트가 양식에서 사용할 수 없는 정보를 필요로 하는 경우와 같이 서버에서 클라이언트로 정보를 전달합니다.예를 들어, 필드 u_retrieve에 액세스해야 하는 클라이언트 스크립트가 있고 필드가 양식에 없으면 클라이언트 스크립트에서 데이터를 사용할 수 없습니다. 이 상황에 대한 일반적인 해결 방법은 필드를 폼에 배치한 다음 클라이언트 스크립트나 UI 정책으로 항상 숨기는 것입니다. 이 솔루션은 구성 속도가 빠를 수 있지만 실행 속도가 느립니다.
양식이 로드되기 전에 클라이언트가 서버에서 필요로 하는 정보를 알고 있는 경우 표시 비즈니스 규칙에서 이 정보를 저장할 g_scratchpad 속성을 만들 수 있습니다. 양식이 요청될 때 Theg_scratchpad 클라이언트로 전송되므로 모든 클라이언트 측 스크립팅 메서드에서 사용할 수 있습니다. 이것은 서버에서 클라이언트로 정보를 보내는 매우 효율적인 방법입니다. 하지만 양식이 로드될 때만 이 방법으로 데이터를 로드할 수 있습니다. 비즈니스 규칙은 동적으로 트리거할 수 없습니다. 이러한 경우 비동기 GlideAjax 호출을 사용합니다.
- 시스템 속성 css.base.color의 값
- 현재 기록에 첨부 파일이 있는지 여부
- 호출자의 관리자 이름
g_scratchpad.css = gs.getProperty('css.base.color');
g_scratchpad.hasAttachments = current.hasAttachments();
g_scratchpad.managerName = current.caller_id.manager.getDisplayValue();// Check if the form has attachments
if (g_scratchpad.hasAttachments)
// do something interesting here
else
alert('You need to attach a form signed by ' + g_scratchpad.managerName);비동기 GlideAjax를 사용하여 서버 데이터 검색
비동기 GlideAjax를 사용하면 서버에서 동적으로 정보를 요청할 수 있습니다.
//Alert if the assignment groups name matches the support group
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading)
return;
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getCiSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.addParam('sysparm_ag', g_form.getValue('assignment_group'));
ga.getXML(doAlert); // Always try to use asynchronous (getXML) calls rather than synchronous (getXMLWait)
}
// Callback function to process the response returned from the server
function doAlert(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
alert(answer);
}var ciCheck = Class.create();
ciCheck.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getCiSupportGroup: function() {
var retVal = ''; // Return value
var ciID = this.getParameter('sysparm_ci');
var agID = this.getParameter('sysparm_ag');
var ciRec = new GlideRecord('cmdb_ci');
// If we can read the record, check if the sys_ids match
if (ciRec.get(ciID)) {
if (ciRec.getValue('support_group') == agID)
retVal = 'CI support group and assignment group match';
else
retVal = 'CI support group and assignment group do not match';
// Can't read the CI, then they don't match
} else {
retVal = 'CI support group and assignment group do not match';
}
return retVal;
}
});참조 필드에 setValue() displayValue 매개변수 사용
참조 필드에서 setValue()를 사용하는 경우 추가 서버 호출을 방지하기 위해 displayValue 매개 변수를 포함합니다.
참조 필드에서 setValue() 를 사용하는 경우 참조 필드 표시 값을 세 번째 매개변수로 포함해야 합니다. displayValue 없이 값을 설정하면 인스턴스는 동기 호출을 수행하여 지정한 레코드의 표시 값을 검색합니다. 서버에 대한 이러한 추가 왕복은 성능에 영향을 줄 수 있습니다.
var id = '5137153cc611227c000bbd1bd8cd2005';
g_form.setValue('assigned_to', id); // Client needs to go back to the server to
// fetch the name that goes with this IDvar id = '5137153cc611227c000bbd1bd8cd2005';
var name = 'Fred Luddy';
g_form.setValue('assigned_to', id, name); // No server call required클라이언트 스크립트 대신 UI 정책 사용
가능하면 클라이언트 스크립트 대신 UI 정책을 사용하는 것이 좋습니다.
- UI 정책에는 클라이언트 측 작업이 수행되는 순서를 완전히 제어할 수 있는 순서 필드가 있습니다.
- UI 정책에는 필수 또는 읽기 전용 또는 표시 필드를 만들기 위한 스크립팅이 필요하지 않습니다.
클라이언트 스크립트를 사용하여 입력의 유효성 검사
클라이언트 스크립트는 사용자가 입력한 내용을 확인하는 데 사용하는 것이 좋습니다.
이 확인을 수행하면 사용자가 정보를 제출하기 전에 데이터 문제가 있는지 확인하기 때문에 사용자 환경이 개선됩니다.
if (g_form.getValue('impact') == '3' && g_form.getValue('priority') == '1')
g_form.showFieldMsg('impact', getMessage('Low impact now allowed with High priority'), 'error');
클라이언트 스크립트 순서 설정
순서 필드를 사용하여 클라이언트 스크립트의 실행 순서를 제어합니다. 두 개 이상의 클라이언트 스크립트를 동시에 실행한 후 충돌하지 않도록 하려면 스크립트 실행 순서를 추가할 수 있습니다.
시작하기 전에
이 태스크 정보
프로시저
DOM 조작 방지
가능하면 DOM(문서 개체 모델) 조작을 피하십시오. 브라우저가 업데이트될 때 유지 관리 문제가 발생할 수 있습니다.
대신 GlideForm API를 사용하거나 솔루션에 대한 다른 접근 방식을 고려하십시오. 일반적으로 DOM 조작 메서드를 사용할 때는 ID로 또는 CSS 선택기를 사용하여 DOM의 요소를 참조해야 합니다. 기본 DOM 요소를 참조할 때 DOM 내의 요소 ID 또는 배치가 변경되어 코드 작동이 중지되거나 오류가 발생할 위험이 있습니다. 미리 생각하고, 주의를 기울이고, 발생하는 위험을 완전히 이해하십시오. 이러한 개체를 검토하고 가능한 한 DOM 조작 메서드의 사용을 줄이십시오.
전역 클라이언트 스크립트 방지
전역 클라이언트 스크립트는 선택한 테이블이 전역인 모든 클라이언트 스크립트입니다. 전역 클라이언트 스크립트에는 테이블 제한이 없으므로 시스템의 모든 페이지에 로드되어 프로세스에서 브라우저 로드 지연이 발생합니다.
모든 페이지에 이런 종류의 스크립트를로드하는 것은 아무런 이점이 없습니다.
대안으로, 그리고 보다 모듈화되고 확장 가능한 접근 방식을 위해 클라이언트 스크립트를 모든 하위/확장 테이블에 대해 파생될 수 있는 기본 테이블(예: Task[task] 또는 Configuration Item[cmdb_ci])로 이동하는 것이 좋습니다. 이렇게 하면 시스템이 UI의 모든 양식(예: 홈 페이지 또는 Service Catalog와 같이 스크립트가 거의 필요하지 않은 경우)에 스크립트를 로드할 필요가 없습니다.
함수에 코드 포함
클라이언트 스크립트의 코드를 함수 안에 넣습니다.
기능이 없는 클라이언트 스크립트는 변수 범위에 문제를 일으킵니다. 코드가 함수로 묶여 있지 않으면 변수 및 기타 개체를 사용할 수 있으며 다른 모든 클라이언트 측 스크립트에서 공유됩니다. 동일한 변수 이름을 사용하는 경우 충돌할 수 있습니다. 이로 인해 문제를 해결하기 어려운 예기치 않은 결과가 발생할 수 있습니다.
var state = "6";
function onSubmit() {
if(g_form.getValue('incident_state') == state) {
alert("This incident is Resolved");
}
}function onSubmit() {
var state = "6";
if(g_form.getValue('incident_state') == state) {
alert("This incident is Resolved");
}
}이 솔루션은 변수 상태 의 범위가 onSubmit() 함수로 제한되기 때문에 훨씬 더 안전합니다. 따라서 상태 변수는 다른 클라이언트 측 스크립트의 상태 변수와 충돌하지 않습니다.
필요한 스크립트만 실행
시간이 많이 걸리는 스크립트를 불필요하게 실행하지 않으려면 클라이언트 스크립트가 필요한 작업만 수행하도록 하십시오.
다음 예제에서는 초기 코드 샘플의 향상된 기능을 보여 줍니다. 각 예제에서는 성능을 향상시키고 불필요한 호출을 방지하기 위한 스크립트의 특정 개선 사항을 보여 줍니다.
클라이언트 스크립트에는 조건 필드가 없습니다. 즉, onLoad() 및 onChange() 스크립트는 적절한 양식이 로드될 때마다 전체적으로 실행됩니다. 이 예는 구성 항목 필드가 변경될 때 실행되도록 설정된 비효율적인 onChange() 클라이언트 스크립트입니다.
//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading) {
var ciSupportGroup = g_form.getReference('cmdb_ci').support_group;
if (ciSupportGroup != '' && g_form.getValue('assignment_group) != '')
g_form.setValue('assignment_group', ciRec.support_group.sys_id);
}
이 예제는 getReference() 또는 GlideRecord 조회를 비동기 GlideAjax 호출로 대체하여 첫 번째 예제를 개선했습니다.
//Set Assignment Group to support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}
플래그 isLoading 는 onChange 스크립트에서 불필요한 코드가 브라우저 시간을 차지하지 않도록 하는 가장 간단한 방법입니다. 플래그는 isLoading 폼이 로드될 때 실행할 필요가 없는 스크립트의 시작 부분에 사용해야 합니다. 필드가 마지막으로 변경되었을 때 논리가 이미 실행되었을 것이기 때문에 양식 로드 시 이 스크립트를 실행할 필요가 없습니다. isLoading 스크립트에 검사를 추가하면 모든 양식 로드에서 cmdb_ci 조회를 수행할 수 없습니다.
플래그는 템플릿이 isTemplate 로드 중임을 나타냅니다.
//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading) {}; // run during loading
// rest of script here
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
if (newValue != oldValue) {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}//Set Assignment Group to CI's support group if assignment group is empty
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading)
return;
if (newValue) {
if (newValue != oldValue) {
if (g_form.getValue('assignment_group') == '') {
var ga = new GlideAjax('ciCheck');
ga.addParam('sysparm_name', 'getSupportGroup');
ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
ga.getXML(setAssignmentGroup);
}
}
}
}
function setAssignmentGroup(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
g_form.setValue('assignment_group', answer);
}