Jelly 構文の拡張
Apache の Jelly 構文は、フォーム、リスト、UI ページ、および ServiceNow でレンダリングされるその他の多くのものをレンダリングするために使用されます。
Jelly を使用すると、ロジックを静的コンテンツ内に埋め込み、計算された値を静的コンテンツに挿入できます。
Apache のページ http://commons.apache.org/jelly/tags.html には、標準の Jelly タグの概要が記載されています。
名前空間
Jelly は、タグを呼び出すときに複数の名前空間を含めることがよくあります。
「j」名前空間は標準の Jelly ですが、「g」名前空間は ServiceNow スクリプトに固有です。たとえば、<g:evaluate> タグは ServiceNow によって提供され、JavaScript を使用して値を計算できるようにします。標準の Jelly タグ <j:test> は条件を評価するために使用されます。
フェーズ
通常、名前空間によって示されるフェーズには、<j> と <j2> および <g> と <g2> の 2 つがあります。
「2」のない名前空間は処理の最初のフェーズで発生し、UI ページで使用される場合を除いてキャッシュされます。「2」が付いているものはキャッシュされません。効率を向上させて正しい結果を得るために、フェーズ 1 とフェーズ 2 のどちらを使用するかを選択するときは注意が必要です。
名前空間に加えて、静的コンテンツに値を挿入するために使用される構文は、値を指定するフェーズによって異なります。ドル記号と中括弧で値を囲むことで、値がフェーズ 1 に挿入されます。たとえば、${jvar_ref} は、jelly プロセスのフェーズ 1 で値 jvar_ref を挿入します。ドル記号と角括弧で値を囲むことで、値がフェーズ 1 に挿入されます。たとえば、${jvar_ref} は、フェーズ 2 で値 jvar_ref を挿入します。引用符に囲まれた値は文字列として処理されます。たとえば、'[jvar_ref]' は、フェーズ 2 で値 jvar_ref を文字列として挿入します。
<script>
if (confirm("$[gs.getMessage('home.delete.confirm') ]"))
...
</script>
<input type="hidden" id="${jvar_name}" name="${jvar_name}" value="${jvar_value}" class="${jvar_class}" />
If test
Jelly スクリプトでも if ステートメントを使用できます。
true かどうかのテストをするには、次のようにします。
<j:if test="${jvar_something}">...do something...</j:if>
<j:if test="${!jvar_something}">...do something...</j:if>
- ブール値で true
- 文字列で「true」、「yes」、「on」、または「1」
存在するかどうかのテストをするには、次のようにします。
<j:if test="${empty(jvar_something)}">...do something...</j:if>
- null
- 空白文字列
- 長さゼロのコレクション
- キーのないマップ
- 空白のアレイ
set_if
test が true か false かに応じて、変数を 2 つの異なる値のいずれかに設定します。
<g2:set_if var="jvar_style" test="$[gs.getPreference('table.compact') != 'false']"
true="margin-top:0px; margin-bottom:0px;"
false="margin-top:2px; margin-bottom:2px;" />
<g:insert>、<g:inline>、および <g:call>
このページでは、<g:insert>、<g:inline>、および <g:call> の 3 つのタグの比較説明を行います。
<g:insert>
<g:insert> タグは、Jelly ファイルを新しいコンテキストで Jelly に挿入します。これは、Jelly で以前に確立した変数にアクセスできないことを意味します。
<g:insert template="get_target_form_function.xml" />
<g:inline>
<g:inline> タグは、Jelly ファイルを同じコンテキストで Jelly に挿入します。これは、挿入された Jelly が以前に確立した変数にアクセスでき、それらの変数の値を変更できることを意味します。
<g:inline template="element_default.xml" />
<g:call>
より適切にカプセル化するには、<g:call> タグを使用します。関数は、渡された値にのみアクセスできます。Jelly コンテキストは、コール後もコール前と同じように見えます。つまり、ここでグローバル変数を設定して後で読み込むことはできません。また、誤って「jvar_temp」というグローバル変数を設定して、他のユーザーが依存していた変数を上書きすることもできません。
値を渡す必要がある場合は、<g:call> 行にパラメーターの名前を含め、その後に等号と引用符で囲んだ値を続けることで、明示的に行うことができます。
<g:call function="collapsing_image.xml" id="${jvar_section_id}" image="$[jvar_cimg]"
first_section_id="${jvar_first_section_id}" image_alt="${jvar_cimg_alt}"/>
値が渡され、デフォルトまたは必須のパラメーターが必要な場合は、関数で参照される Jelly に、パラメーターが必須かデフォルト値があるかを宣言する行を含める必要があります。
<g:function id="REQUIRED" image="REQUIRED" image_prefix="" image_alt="REQUIRED"/>
上記の例は、3 つのパラメーターが必須であり、1 つのパラメーターが空のデフォルト値を持つオプションであることを示しています。値を渡さない場合、またはデフォルト値や必須値が必要な場合は、<g:function> 行を含める必要はありません。ただし、一般的には <g:function> 行を含めます。
パラメーターの名前の先頭に「jvar_」プリフィックスを追加することで、値をテンプレートで参照できるようになります。
<img id="img.${jvar_id}" src="images/${jvar_image}" alt="${jvar_image_alt}" onclick="toggleSectionDisplay('${jvar_id}', '${jvar_image_prefix}','${jvar_first_section_id}');"/>
<g:call> では、「arguments」パラメーターの名前付き変数のリストとしてパラメーターを暗黙的に渡すこともできます。
<g:call function="item_link_default.xml" arguments="sysparm_view,ref_parent,jvar_target_text"/>
個別のタグ引数を介して関数に変数を渡す代わりに、単一の「arguments」引数で変数のリストを渡すことができます。argument パラメーターの名前 (カンマ区切り) で識別されるすべての変数は、まったく同じ名前で関数内に再導入されます (たとえば、関数テンプレート内では、変数 sysparm_view、ref_parent、および jvar_target_text を使用できます)。
関数テンプレートは、return= 属性を使用して呼び出し元テンプレートに値を返すことができます。関数内では、jvar_answer 変数で戻り値を設定します。
<g:call function="item_body_cell_calc_style.xml" arguments="jvar_type" return="jvar_style"/>
<g:evaluate>
<g:evaluate> タグは、Rhino JavaScript で記述された式を評価するために使用され、場合によっては変数を式の値に設定するために使用されます。
式の最後のステートメントは、変数に含まれる値です。
<g2:evaluate var="jvar_page" jelly="true">
var page = "";
var pageTitle = "";
var pageGR = new GlideRecord("cmn_schedule_page");
pageGR.addQuery("type", jelly.jvar_type");
pageGR.query();
if (pageGR.next()) {
page = pageGR.getValue("sys_id");
pageTitle = pageGR.getDisplayValue();
}
page;
</g2:evaluate>
<g2:evaluate var="not_important" expression="sc_req_item.popCurrent()"/>
object="true"
評価でオブジェクト (アレイなど) を返す場合は、引数 object="true" を使用します。
<g2:evaluate object="true" var="jvar_items" expression="SncRelationships.getCMDBViews()" />
jelly="true"
評価内の Jelly 変数にアクセスする場合は、評価に jelly="true" を含め、Jelly 変数の名前の前に「jelly.」を追加します。たとえば、GlideJellyContext にアクセスするには、次のようにします。
<g2:evaluate var="jvar_row_no" jelly="true">
var gf = jelly.context.getGlideForm();
var row = gf.getRowNumber();
row;
</g2:evaluate>
jelly="true" パラメーターを使用して jvar にアクセスする別の例を示します。jvar_h の値は以前に設定されており、evaluate 内でアクセスできます。
$[NLBR:jvar_h.getHTMLValue('newvalue')]
<g2:evaluate var="jvar_fix_escaping" jelly="true">
var auditValue = jelly.jvar_h.getHTMLValue('newvalue');
gs.log("************ " + auditValue);
</g2:evaluate>
copyToPhase2="true"
フェーズ 1 での評価結果を取得してフェーズ 2 に伝播する必要がある場合は、copyToPhase2="true" を使用します。この使い方をする場合、エスケープに対する保護がいくつかあります。例:
<g:evaluate var="jvar_has_special_inc" copyToPhase2="true">
var specialInc = gs.tableExists("special_incident");
specialInc;
</g:evaluate>
$[jvar_has_special_inc]
何も評価する必要がない場合は、より直接的に行うことができます。この時、エスケープの問題に注意してください (この例では、jvar_rows 内の二重引用符で問題が発生します)。
<j2:set var="jvar_rows" value="${jvar_rows}"/>
<g:breakpoint/>
このタグを使用して、現在の Jelly 変数とその値をログに表示できます。
本番環境に移行する前に、このタグを必ず削除してください。
<g:ui_form/>
このタグは、UI ページのフォームを定義します。
たとえば、フォームに application_sys_id フィールドが含まれている場合、g:ui_form で処理スクリプトを使用するメリットがある可能性があります。
<g:ui_form>
<p>Click OK to run the processing script.</p>
<g:dialog_buttons_ok_cancel ok="return true" />
<input type="hidden" name="application_sys_id" value="499836460a0a0b1700003e7ad950b5da"/>
</g:ui_form>
詳細については、「UI マクロ」を参照してください。
<g:ui_input_field />
このタグを使用することで、ユーザーが情報を入力できるページに入力フィールドを作成する UI マクロへの参照を追加できます。ui_input_field は、ラベル、名前、値、サイズを UI マクロに渡します。
<g:ui_input_field label="sys_id" name="sysid" value="9d385017c611228701d22104cc95c371" size="50"/>詳細については、「UI マクロ」を参照してください。
<g:ui_checkbox/>
このタグを使用することで、ユーザーが編集可能なチェックマークをページに配置することができます。名前と値は UI マクロに渡されます。
UI ページのテーブルの例を次に示します。
<table>
<tr>
<td nowrap="true">
<label>Time Card Active:</label>
</td>
<td>
<g:ui_checkbox name="timecard_active" value="${sysparm_timecard_active}"/>
</td>
</tr>
</table>
詳細については、「UI マクロ」を参照してください。
<g:dialog_buttons_ok_cancel/>
このタグを使用することで、タグが true を返した場合に、指定された処理スクリプトを実行するボタンを UI ページに配置することができます。
UI ページにフォームが含まれている (<g:form> タグを使用している) 場合は、フォームを送信して処理スクリプトを実行できます。処理スクリプトは、フォーム上のフィールドに自然にアクセスできます。たとえば、フォームに application_sys_id フィールドが含まれている場合は、次のようにします。
<g:ui_form>
<p>Click OK to run the processing script.</p>
<g:dialog_buttons_ok_cancel ok="return true" />
<input type="hidden" name="application_sys_id" value="499836460a0a0b1700003e7ad950b5da"/>
</g:ui_form>
<g:ui_reference/>
このタグは、処理スクリプトで参照できるページへの参照を追加します。
次の例では、タグ内の名前、ID、およびテーブルパラメーターで定義された参照を作成します。
<g:ui_reference name="QUERY:active=true^roles=itil" id="assigned_to" table="sys_user" />
次に、処理スクリプトで、次のように [名前] フィールドを参照します。
newTask.assigned_to = request.getParameter("QUERY:active=true^roles=itil");
<g:ui_reference name="parent_id" id="parent_id" table="pm_project" query="active=true" completer="AJAXTableCompleter"
columns="project_manager;short_description"/>
アンパサンド
Jelly は XML であるため、Jelly でアンパサンドを使用すると問題が発生する可能性があります。
Jelly でアンパサンドを挿入するには、${AMP} を使用します。実際にブラウザーで実行される UI ページや UI マクロなどの HTML 部分に表示される JavaScript を記述する場合は、このコードを [クライアントスクリプト] フィールドに入力することをお勧めします。そうすることで、エスケープの問題を回避できます。ただし、どうしても [HTML] フィールドに入力する必要がある場合は、次のようにする必要があります。
ta = ta[1].split('$[AMP]');
AND
${AND} を使用して、Jelly で JavaScript を挿入します。
例:
if (d ${AND} e)
var color = d.value;
または、Jelly の test では「&&」を使用します。例:
<j:if test="${jvar_form_name == 'sys_form_template' && !RP.isDialog()}">
次の値未満
アンパサンドと同様に、Jelly は XML であるため、小なり記号 (「<」) でも問題が発生する可能性があります。これは、test が不要になるように変更するか、小なり記号の代わりに ${AMP}lt; を使用することで解決できます。
<g2:evaluate var="jvar_text">
var days = "";
var selectedDays = '$[${ref}]';
for (var i = 1; i ${AMP}lt;= 7; i++) {
if (selectedDays.indexOf(i.toString()) >= 0) {
days += gs.getMessage("dow" + i);
days += " ";
}
}
days;
</g2:evaluate>
多くの場合、エスケープの問題がない「次の値に等しくない」演算子を使用するだけで、「次の値未満」演算子をまとめて回避できます。例:
for (var i=0; i != ta.length; i++) {
}
whitespace
通常、空白は Jelly によって削除されます。保持するには、トリミングされないように指定する必要があります。
たとえば、次の例では、コロンの後にスペースが保持されます。
<j2:whitespace trim="false">${gs.getMessage('Did you mean')}: </j2:whitespace>
スペース
改行なしスペース ( ) をエンコードするには、 $[SP] を使用できます。
例:
<span id="gsft_domain" style="display: inline">
${gs.getMessage('Domain')}:$[SP]
<span id="domainDD" class="drop_down_element" style="text-decoration: none; color: white">
${gs.getMessage("Loading...")}
</span>
</span>
Jelly のトレース
ServiceNow には、Jelly の評価をトレースできる機能があります。
トレースがログに送信されます。多くのログが生成されるため、これはデバッグ中にのみオンにしてください。トレースをオンにするには、プロパティ glide.ui.template.trace を true に設定します。たとえば、次のスクリプトを実行してこれを行うことができます。
GlideProperties.set ( 'glide.ui.template.trace' , true ) ;
各ページの下部にある Web ブラウザーでログエントリを確認する場合は、 .