イベントとしてではなく、休日や祝日のときはセル(TD要素です)の色(もしくは、TD要素としてのその他の属性やスタイル)を変更したい、との相談がありました。
Oracle APEXのカレンダ・リージョンの実体はFullCalendarのv6です。FullCalendarのドキュメントを確認すると、Day-Cell Render Hooksという機能が見つかりました。このフックの内のdayCellDidMountを使って実装してみました。
以下、dayCellDidMountのフックを使って、祝日にあたる日付セルの背景色を変えてみました。
以下より、実装について紹介します。
最初に日本の祝日のデータをデータベースにロードします。以前の記事に合わせて祝日を保持する表として、表CAL_NATIONAL_HOLIDAYSを作成します。以下のDDLを実行します。
create table cal_national_holidays (
id number generated by default on null as identity
constraint cal_national_holidays_id_pk primary key,
holiday_date date,
holiday_name varchar2(255 char)
);
SQLワークショップのSQLコマンドでの実行例です。
表CAL_NATIONAL_HOLIDAYSに日本の祝日のデータをロードします。データ・ロード自体は本記事の本題ではないので、手短に以下のスクリプトを実行してデータをロードします。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_blob blob; | |
e_get_content_failed exception; | |
l_num_rows number; | |
begin | |
/* 最初に祝祭日を全消去 */ | |
delete from cal_national_holidays; | |
/* 内閣府から国民の祝日のファイルを取得 - SJISなのでバイナリ扱い */ | |
apex_web_service.clear_request_headers(); | |
l_blob := apex_web_service.make_rest_request_b( | |
p_url => 'https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv' | |
,p_http_method => 'GET' | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise e_get_content_failed; | |
end if; | |
/* CSVをパースして表CAL_NATIONAL_HOLIDAYSに投入 */ | |
for r in ( | |
select col001, col002 from table( | |
apex_data_parser.parse( | |
p_content => l_blob | |
,p_file_name => 'dummy.csv' -- to recognize the data as CSV | |
,p_file_charset => 'JA16SJIS' | |
,p_skip_rows => 1 | |
) | |
) | |
) | |
loop | |
insert into cal_national_holidays(holiday_date, holiday_name) | |
values(to_date(r.col001, 'YYYY/MM/DD'), r.col002); | |
end loop; | |
commit; | |
/* 実行結果 */ | |
select count(*) into l_num_rows from cal_national_holidays; | |
dbms_output.put_line(apex_string.format('表CAL_NATIONAL_HOLIDAYSに%s行のデータが存在します。', l_num_rows)); | |
end; |
SQLコマンドでの実行例です。表CAL_NATIONAL_HOLIDAYSに挿入された行数が報告されます。
空のAPEXアプリケーションを作成します。名前はFullCalendar Cell Highlightとしています。サンプルの実装は、ホーム・ページに行っています。
実装に使うカレンダのリージョンを作成します。ソースのタイプをSQL問合せとし、SQL問合せとして以下を記述します。SELECT文の列情報を参照するだけなので、条件句として 1<>1を指定して、どのような場合でも1行も値を返さないようにしています。
select 'TITLE' as title, date'2001-01-01' as start_date from dual where 1<>1
JavaScriptよりリージョンを参照するため、静的IDとしてCALENDARを割り当てています。
カレンダの属性を開き、設定の表示列にTITLE、開始日列にSTART_DATEを設定します。
以上で最低限のカレンダの設定ができました。
続いて、国民の祝日のデータをJavaScriptから参照できるようにします。祝日の確認の度にデータベースに問い合わせるのは現実的では無いため、ページ・ロード時にデータベースから国民の祝日のデータを取り出し、JavaScriptのグローバル変数に保存します。
データベースから国民の祝日のデータを取り出す処理を、Ajaxコールバックのプロセスとして作成します。プロセス名はGET_HOLIDAYSとします。
ソースのPL/SQLコードとして以下を記述します。
declare
l_holidays clob;
begin
select
json_objectagg(to_char(holiday_date,'YYYY-MM-DD') value holiday_name returning clob)
into l_holidays
from cal_national_holidays;
htp.p(l_holidays);
end;
国民の祝日の情報は、以下のようなJSONドキュメントとしてGET_HOLIDAYSの呼び出し元に返されます。
{
"1988-11-23": "勤労感謝の日",
"1989-01-01": "元日",
"1989-01-02": "休日",
"1989-01-15": "成人の日",
"1989-01-16": "休日",
"1989-02-11": "建国記念の日",
....
"2025-10-13": "スポーツの日",
"2025-11-03": "文化の日",
"2025-11-23": "勤労感謝の日",
"2025-11-24": "休日"
}
カレンダの日付セルの変更に関わる実装を行います。
ページ・プロパティのJavaScriptのファンクションおよびグローバル変数の宣言に以下を記述します。
/*
* 国民の祝日を保持する。
*/
var g_HOLIDAYS = {};
/*
* 日付セルの要素と日付データを受け取り、祝日が設定されていれば
* 日付セルを変更する。
*
* 以下は例としてCSSクラスu-color-18-bgを設定している。
*/
const modifyDayIfHoliday = (elem, date) => {
const year = date.getFullYear();
const month = String(date.getMonth()).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const key = `${year}-${month}-${day}`;
if ( g_HOLIDAYS[key] !== undefined ) {
elem.classList.add('u-color-18-bg');
}
};
ページ・ロード時に実行に以下を記述します。ページ・ロード時はdayCellDidMountのフックが呼び出されません。そのため、祝日データの読み込みが完了した後に、表示されているすべての日付セルを対象に、dayCellDidMountフックの代わりにmodifyDayIfHolidayを呼び出します。
/*
* 休日のデータをHOLIDAYSにキャッシュした後に、
* 日付セルに祝日処理を適用する。
*/
apex.server.process( "GET_HOLIDAYS", {},
{
success: (data) => {
g_HOLIDAYS = data;
/* 表示されているカレンダに色付けをする */
const calEl = document.getElementById("CALENDAR");
const cells = calEl.querySelectorAll('td[role="gridcell"]');
cells.forEach( (e) => {
const date = e.getAttribute('data-date');
modifyDayIfHoliday(e, new Date(date));
});
}
}
);
カレンダにdayCellDidMountフックを設定します。属性の詳細の初期化JavaScriptファンクションに以下を記述します。
function( options ) {
options.dayCellDidMount = (e) => {
modifyDayIfHoliday(e.el, e.date);
}
}
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/fullcalendar-cell-highlight.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完