2024年6月6日木曜日

対話グリッドのセルへのマウス・エンターとマウス・リーブを確認する

対話グリッドのセルに対して、マウス・エンターとマウス・リーブのイベントで呼び出される動的アクションを作成したところ、当初考えていたように動きませんでした。

動作を確認するためのAPEXアプリケーションを作成し、対話グリッドセルターゲットとしたマウス・エンターマウス・リーブイベントで呼び出される動的アクションを作成します。

動作の確認には、サンプル・データセットEMP/DEPTに含まれる表EMPをソースとした、編集可能対話グリッドを使用します。動的アクションは列ENAMEに作成します。対話グリッドのリージョンに、静的IDとしてempを設定します。

最初は、素直に対話グリッドのに動的アクションを作成します。

識別名前Enterとします。実行イベント有効範囲動的静的コンテナ(jQueryセレクタ)#empとします。対話グリッドのセルはページのリロードをせずに書き換わるため、イベント有効範囲動的にしています。

タイミングイベントマウス・エンター選択タイプENAMEを指定します。マウス・エンターイベントが発生したときに実行されるJavaScriptコードは以下です。
console.log(this.triggeringElement);
apex.items.P2_ENTER.setValue($v(this.triggeringElement));

マウス・リーブのイベントで呼び出される動的アクションも作成します。イベントマウス・リーブになるのと、実行されるJavaScriptコードが異なります。
console.log(this.triggeringElement);
apex.items.P2_LEAVE.setValue($v(this.triggeringElement));

ページを実行してマウス・エンターおよびマウス・リーブのイベントの発生を確認すると、イベントのトリガー要素(this.triggeringElement)が、INPUT要素であることが確認できます。

<input type="text" id="C22499063937843927" name="22499063937843927" class="text_field apex-item-text js-ignoreChange" value="" maxlength="50" tabindex="0" aria-labelledby="C22499063937843927_HDR">


対話グリッドのセルがINPUT要素になるのは、セルをダブルクリックなどして編集する状態になったときです。セルが表示されているときはINPUT要素ではないため、その状態のセルにポインタを載せてもイベントは発生しません。

対話グリッドの列に動的アクションを作成する場合、タイミング選択タイプ対話グリッドの3つを指定します。この形式で指定すると、編集モードになったセルがトリガー要素になることがわかりました。

編集モードになったセルではなく、表示されているセルがトリガー要素になる設定を探してみます。

ENAME詳細CSSクラスに、擬似CSSクラスとしてonPointerを設定します。


マウス・エンター/リーブのタイミング選択タイプjQueryセレクタに変更し、jQueryセレクタとして.onPointerを指定します。

列ENAMEの一番内部の要素がトリガー要素になります。


ページを実行してマウス・エンターおよびマウス・リーブのイベントの発生を確認します。

先ほどの列ENAMEに動的アクションを作成したときと同じ動作が確認できます。対話グリッドの詳細CSSクラスは、INPUT要素に設定されています。そのため、この設定では表示中のセルをターゲットとしたマウス・イベントは取れません。


ENAME詳細CSSクラスとして設定したonPointerを削除し、代わりに外観CSSクラスとして設定します。


動的アクションのタイミングはCSSクラスonPointerに設定されているため変更は不要ですが、実行するJavaScriptは$v(this.triggeringElement)の代わりにthis.triggeringElement.textContentをページ・アイテムに設定するように変更します。
console.log(this.triggeringElement);
apex.items.P4_ENTER.setValue(this.triggeringElement.textContent);
ページを実行してマウス・エンターおよびマウス・リーブのイベントの発生を確認すると、イベントのトリガー要素(this.triggeringElement)が、TD要素であることが確認できます。

<td tabindex="-1" role="gridcell" class="a-GV-cell u-tS onPointer">MARTIN</td>

この場合はセルが編集モードになる必要はなく、セルの上にマウスが載ったらマウス・エンター、離れたらマウス・リーブのイベントが発生します。


外観CSSクラスの代わりに列ENAMEcellTemplateを設定します。
function(options) {
    options.defaultGridColumnOptions = {
        cellTemplate: '<div class="onPointer">&ENAME.</div>'
    }
    return options;
}
この場合、cellTemplateとして設定した要素がトリガー要素になります。セルが編集モードになる必要はありません。

<div class="onPointer">TURNER</div>


外観CSSクラスとして擬似クラスonPointerを設定しても、cellTemplateのclass指定にonPointerを含めても、表示モードのセル上でマウス・エンター/リーブのイベントを取ることができます。

cellTemplateを使うとカスタム属性などを追加できるため、呼び出されるJavaScriptの記述が楽になるという利点があります。例えばcellTemplateにカスタム属性data-idとして従業員番号を渡します。
function(options) {
    options.defaultGridColumnOptions = {
        cellTemplate: '<div data-id=&EMPNO. class="onPointer">&ENAME.</div>'
    }
    return options;
}
動的アクションで呼び出されるJavaScriptでは、this.triggeringElement.dataset.idとして従業員番号を参照できます。
console.log(this.triggeringElement);
apex.items.P5_ENTER.setValue(this.triggeringElement.textContent);
apex.items.P5_EMPNO.setValue(this.triggeringElement.dataset.id);

今回の記事は以上です。

今回の作業で使用したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/mouse-event-on-ig.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。