2022年11月29日火曜日

CSSのhas擬似クラスを使ったレポートのセルの色付け

 対話モード・レポートのセルに色を付けるために、対話モード・レポートのリフレッシュ後にJavaScriptを実行しているのだけど実装として今ひとつ。もっと良い方法は無いものか?という話がありました。

対話モード・レポートとしては以下のようになります。一番上はJavaScriptでセルに色付けを行っています。真ん中は対話モード・レポートの標準的な機能の範囲での実装です。最後はCSSの擬似クラスhasを使っています。


対話モード・レポートのソースとなるSELECT文は、すべて同じです。Oracle APEXに付属しているサンプル・データセットEMP/DEPTに含まれる表EMPをソースとしています。

給与(列SALのデータ)が1000より少ない時に列COLORの値がredになります。
select EMPNO,
       ENAME,
       JOB,
       MGR,
       HIREDATE,
       SAL,
       COMM,
       DEPTNO
       , case
       when sal < 1000 then 'red'
       else ''
       end color
  from EMP


APEXの標準の範囲での実装


SAL列の書式HTML式として、以下を設定しています。

<span style="background-color:#COLOR#;">#SAL#</span>


この設定で、列SALの値の背景色が赤になります。APEXでは、その親の要素の属性を変更する方法が提供されていないため、TD要素の背景色を変更できません。

結果として、セル全体の背景色の設定ができていません。


JavaScriptによる実装



JavaScriptによってセルの背景色を変更するために、列SALdata-color属性として色情報を含めるようにします。これも列の書式HTML式として設定します。

<span data-color="#COLOR#">#SAL#</span>


対話モード・レポートのリフレッシュ後に、動的アクションとして以下のJavaScriptを実行します。data-colorとして定義した値を、親の要素の背景色として設定しています。

document.querySelectorAll("#emp0 span[data-color]").forEach(
    (e) => {
        e.parentElement.style.backgroundColor = e.dataset.color;
    }
);
動的アクションは、初期化時にも実行するように設定します。


以上でセルの背景色が設定されます。


CSSの擬似クラスhasによる実装



動的アクションを作成する代わりに、ページ・プロパティCSSインラインに以下を記述します。
#emp2 td:has(span[data-color=red]) {
    background-color: red;
}

擬似クラスhasはFirefoxではまだサポートされていないようで、使うべきかどうかは迷うところではあります。それでもCSSで設定できるほうが、JavaScriptよりは有望です。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/css-has-cell-coloring.zip

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