2022年9月2日金曜日

CKEditor5のmention機能を実装してみる

追記: APEX 23.1よりリッチ・テキスト・エディタはCKEditor5からTinyMCEへ置き換えられます。CKEditor5のカスタマイズ方法はTinyMCEには適用できません。

---- 

 Louis Moreauxさんが彼のブログにCKEditor5 mention featureという記事を載せていました。面白い内容だったので、自分でも実装してみました。


日本語環境だとmentionの機能を使った直後のキーボード入力がIMEに渡らないようです。私が使っているMacの問題かもしれませんが、少々残念です。

以下より、上記のサンプル・アプリケーションを作ったときの作業を記述します。今回はテスト・データの生成にOracle APEX 22.1の新機能であるデータ・ジェネレータを使いました。

クイックSQLを使って、ユーザーの一覧を保存する表CKE_USERSを作成します。

SQLワークショップユーティリティクイックSQLを開きます。クイックSQLモデルとして以下を記述します。
# prefix: cke
users
    first_name vc80 /nn
    last_name  vc80 /nn
    email_address vc40
    shortname  vc8 /nn
SQLの生成SQLスクリプトを保存レビューおよび実行を順次クリックします。表の作成までを実施し、アプリケーションの作成は行いません。


CKE_USERSが作成されます。


作成した表CKE_USERSにテスト・データを投入します。

 SQLワークショップユーティリティデータ・ジェネレータを開きます。

作成済みのブループリントが一覧されます。生成するテスト・データの定義は、ブループリントというJSON形式のファイルとして保存されます。

ブループリントの作成をクリックします。


ブループリントの作成方法を選択します。今回は先ほど作成した表CKE_USERSを元にブループリントを作成します。

既存の表の使用を選択します。


ブループリント名CKEditor5 Mention Testとします。表の一覧よりCKE_USERSチェックを入れます。

以上の設定を行い、ブループリントの作成をクリックします。


ブループリントが作成され、ブループリント・デザイナが開きます。


TablesにあるCKE_USERSを選択し、設定を確認します。

行数50行になっています。このブループリントを元に生成されるテスト・データは50行です。名前として設定されているCKE_USERSに50行のテスト・データが挿入されます。


IDを選択します。

データ・ソースとして組込み組込みとしてnumber.guid:NUMBERが設定されています。sys_guid()の結果が列IDのテスト・データとして生成されます。しかし、列IDは自動生成になっており、値を投入すると一意性を担保できなくなります。

IDをテスト・データ生成の対象から外すため、列の削除を実行します。


FIRST_NAMEを選択します。データ・ソース組込み組込みとしてperson.first_name:VARCHAR2が選択されています。Oracle APEXが事前定義しているperson.first_nameのデータが、テスト・データとして使用されます。現在のところ英語のデータのみで、詳細言語en以外は選択できません。最大長は表CKE_USERSの列FIRST_NAMEのサイズを考慮していないようです。表定義に合わせて最大長80に変更します。


LAST_NAMEを選択します。こちらも最大長80に変更します。


EMAL_ADDRESSを選択します。データ・ソース組み込み組み込みとしてperson.email:VARCHAR2が選択されています。列名から推測して、テスト・データが選択されています。必須OFFにして、パーセント・ブランク10とします。テスト・データとして50行生成するように設定しているので、そのうちの10%である5行は列EMAIL_ADDRESSがNULLになります。詳細最大長40とします。


SHORTNAMEを選択します。データ・ソースとしてを選択し、として以下を記述します。

upper(substr({FIRST_NAME},1,1) || substr({LAST_NAME},1,7))

列FIRST_NAMEの先頭1文字と列LAST_NAMEの先頭7文字を連結した、最大8文字の値を列SHORTNAMEとして生成します。


以上でブループリントが作成できました。

データのプレビューをクリックして、生成されるテスト・データを確認します。

FIRST_NAMELAST_NAMEEMAIL_ADDRESS、それとによって定義している列SHORTNAMEも想定したテスト・データになっています。

プレビューを確認した後、データの作成に進みます。


アクションとしてデータベースへの挿入を選択します。生成されたテスト・データは表CKE_USERSへ直接書き込まれます。挿入メソッド挿入行スケーリング1xとします。

アクションとしてファイル・エクスポートを選択すると、JSONCSVまたはSQLのinsert文としてテスト・データをファイルに出力できます。生成したテスト・データを別のプラットフォームにロードする際に役立つでしょう。

データを挿入を実行します。


テスト・データが挿入されるとダイアログにメッセージが表示されますが、ダイアログは閉じません。続けてデータを挿入を実行すると、さらにテスト・データが挿入されます。今回の例では50行が追加され、100行になります。

テスト・データの作成が終わったら、取消をクリックしてダイアログを閉じます。


SQLワークショップオブジェクト・ブラウザなどを使用して、表CKE_USERSに投入されたテスト・データを確認します。


表CKE_USERSとテスト・データの準備ができたので、CKEditor5のmentionの機能を使うAPEXアプリケーションを作成します。

アプリケーション作成ウィザードを起動します。

アプリケーションの名前CKEditor5 mention featureとします。それ以外は変更せず、アプリケーションの作成を実行します。

アプリケーションはすべてホーム・ページに実装します。


アプリケーションが作成されたら、ホーム・ページページ・デザイナで開きます。


ページ・アイテムP1_TEXTを作成します。このページ・アイテムのタイプリッチ・テキスト・エディタ(実体はCKEditor5)とし、mentionを使えるようにします。

識別名前P1_TEXTタイプとしてリッチ・テキスト・エディタを選択します。ラベルTextとします。ソースタイプNULL使用セッション・ステートの値がNULLの場合のみセッション・ステートの保持セッションごと(ディスク)を選択します。

ページ・アイテムP1_TEXTの値はセッション・ステートにのみ保存し、表やAPEXコレクションは用意しません。


送信ボタンを作成します。

識別ボタン名B_SUBMITラベルSubmitとします。動作アクションとしてページの送信を選択します。

このボタンをクリックすると、ページ・アイテムP1_TEXTの値がセッション・ステートに保存されます。


ページ・アイテムを作成し、mentionとして検索される数の上限を設定します。

識別名前P1_LIMITタイプとして非表示を選択します。ソースタイプとして静的値を選択し、静的値5を指定します。一度に検索されるmentionの上限を5に設定しています。使用はセッション・ステートの値がNULLの場合のみセッション・ステートの保持リクエストごと(メモリーのみ)を選択します。


CKEditor5が発行する検索要求を受け付けて、ユーザーの一覧を返すAjaxコールバックを作成します。

Ajaxコールバックにプロセスを作成します。

識別名前GET_USERSタイプとしてコードを実行を選択します。ソースPL/SQLコードとして、以下を記述します。




CKEditor5のプラグインmentionを有効にします。

ページ・アイテムP1_TEXT詳細JavaScript初期化コードとして、以下を記述します。




初期化コードで呼び出しているファンクションgetUserItemsuserItemRendererを、ページ・プロパティJavaScriptファンクションおよびグローバル変数の宣言に記述します。



以上でAPEXアプリケーションは完成です。

アプリケーションを実行すると、記事の先頭にあるGIF動画のような動作をします。

開発者ツール・バーよりセッション・ステートを表示させ、ページ・アイテムP1_TEXTに保存されているHTML文書を確認します。


入力した文字列は以下のようになります。

<div class="ck-content"><p><span class="mention" data-mention="@PMOREL">Parker Morel</span> さんへ、</p><p>mention機能については、 <span class="mention" data-mention="@WPICKENP">Winter Pickenpaugh</span> さんへ、</p></div>

mentionの部分に限ると、以下です。data-mention属性としてAjaxコールバックGET_USERSがidとして返した値、span要素テキストとしてtextが設定されています。

<span class="mention" data-mention="@PMOREL">Parker Morel</span>

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

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