クライアント側のスクリプティングの設計と処理
クライアントスクリプトを適切に設計すれば、ユーザーのフォーム入力時間を短縮できます。
クライアント側の処理が適切に行われるようにするには、最初にフォームを読み込みます。フォームの読み込み前にレコードを更新すると、予期しない結果が発生し、クライアント側の処理がバイパスされる可能性があります。
- テーブルのリスト編集を無効にします。
- リスト編集に適したビジネスルールまたはアクセス制御を作成します。
- データポリシーを作成します。
- onCellEdit クライアントスクリプトを別に作成します。
リストの編集の制限
フォーム上のフィールドに対して UI ポリシーまたはクライアントスクリプトを作成する場合、別の方法を使用して、それらのフィールドのデータがリストで同様に制御されるようにする必要があります。
- テーブルのリスト編集を無効にします。
- リスト編集に適したビジネスルールまたはアクセス制御を作成します。
- データポリシーを作成します。
- onCellEdit クライアントスクリプトを別に作成します。
サーバールックアップを最小限に抑制
クライアントデータをできるだけ使用することで、時間のかかるサーバールックアップが必要なくなります。
クライアントスクリプティングでは、クライアントで利用可能なデータまたはサーバーから取得したデータのいずれかを使用します。サーバーから情報を取得する主な方法は、g_scratchpad と非同期 GlideAjax ルックアップです。
これらの方法の主な違いは、g_scratchpad ではフォームがロードされたときに 1 回送信される (情報がサーバーからクライアントにプッシュされる) のに対し、GlideAjax はクライアントがサーバーに情報を要求すると動的にトリガーされることです。
g_scratchpad を使用したサーバーデータの取得
g_scratchpad オブジェクトは、クライアントがフォーム上で利用できない情報を必要とする場合に、サーバーからクライアントに情報を渡します。たとえば、フィールド u_retrieve にアクセスする必要があるクライアントスクリプトがあり、そのフィールドがフォーム上にない場合、クライアントスクリプトはデータを使用できません。この状況の一般的な解決策は、フォームにフィールドを配置してから、クライアントスクリプトまたは UI ポリシーを使用して常に非表示にすることです。このソリューションは素早く構成できますが、実行は遅くなります。
フォームがロードされる前にクライアントがサーバーから必要とする情報がわかっている場合は、表示ビジネスルールでこの情報を保持する g_scratchpad プロパティを作成できます。g_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() を使用する場合は、必ず参照フィールドの表示値を 3 番目のパラメーターとして含めてください。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');
クライアントスクリプトの順序の設定
[順序] フィールドを使用して、クライアントスクリプトの実行順序を制御します。2 つ以上のクライアントスクリプトが同時に実行されて競合することを避けるために、スクリプトを実行する順序を追加できます。
始める前に
このタスクについて
手順
DOM 操作の回避
可能であれば、ドキュメントオブジェクトモデル (DOM) の操作は避けてください。ブラウザーが更新されたときに、保守性の問題が発生する可能性があります。
代わりに、GlideForm API を使用するか、別の方法での解決を検討してください。一般に、DOM 操作メソッドを使用する場合は、ID または CSS セレクターを使用して DOM 内の要素を参照する必要があります。すぐに利用可能な DOM 要素を参照する場合、DOM 内の要素 ID または配置が変更され、コードが機能しなくなったり、エラーが生成されたりするリスクがあります。事前に慎重に検討し、発生しているリスクを十分に理解してください。これらのオブジェクトを確認し、DOM 操作メソッドの使用をできるだけ減らします。
グローバルクライアントスクリプトを避ける
グローバルクライアントスクリプトは、選択したテーブルがグローバルである任意のクライアントスクリプトです。グローバルクライアントスクリプトにはテーブルの制限がないため、システム内のすべてのページでロードされ、プロセスでブラウザーのロード遅延が発生します。
この種のスクリプトをすべてのページにロードするメリットはありません。
別の方法として、すべての子/拡張テーブルから派生できるベーステーブル (タスク [task] や構成アイテム [cmdb_ci] など) にクライアントスクリプトを移動する、よりモジュール式でスケーラブルなアプローチを検討してください。これにより、スクリプトをめったに必要としないホームページや Service Catalog など、UI のすべてのフォームでスクリプトをロードする必要がなくなります。
関数でコードを囲む
関数内のクライアントスクリプトでコードを囲みます。
関数のないクライアントスクリプトは、変数スコープに関する問題の原因となります。コードが関数で囲まれていない場合、変数やその他のオブジェクトは使用可能で、他のすべてのクライアント側のスクリプトで共有されます。同じ変数名を使用している場合は、競合する可能性があります。これにより、トラブルシューティングが困難な予期しない結果が生じる可能性があります。
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");
}
}このソリューションは、変数 state のスコープが onSubmit() 関数に制限されているため、はるかに安全です。したがって、state 変数は、他のクライアント側のスクリプトの state 変数と競合しません。
必要なスクリプトのみを実行する
時間のかかるスクリプトを不必要に実行しないようにするには、クライアントスクリプトが必要なタスクのみを実行するようにします。
次の例は、最初のコードサンプルの改善を示しています。各例は、パフォーマンスを向上させ、不要な呼び出しを回避するためのスクリプトの特定の拡張を示しています。
クライアントスクリプトには [条件] フィールドがないことに注意してください。これは、適切なフォームがロードされるたびに、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);
}