CKEditorのダイアログ中のテキストをJSで置換する方法(試行錯誤の記録)

【結論】

・CKEditorのダイアログ中のテキストは、idが固定では無く、classは別のダイアログと共通化されているので、それらを使って文字の置換が困難

・ダイアログ(JavaScript)の生成にフックするdialogDefinition イベントにコールバックを設定し動的にカスタマイズする方法であれば実装可能

・ファイル一式をホストして、直接ファイルを書き換える方法でも実装できるかもしれない

【目次】

【本題】

結論(コードとbefore/after画像)

以下のコードで、画像の通りCKEditorのダイアログ中のテキストを置換できましたという話。

CKEDITOR.on('dialogDefinition', function (ev) { // eslint-disable-line no-undef
  var dialogName = ev.data.name;
  var dialogDefinition = ev.data.definition;

  if (dialogName === 'templates') {
    dialogDefinition.title = '画像配置パターン';
    var selectTplText = dialogDefinition.getContents('selectTpl').elements[0].children;
    selectTplText[0].html = '<span>画像配置パターンを選択してください。</span>';
    delete selectTplText[2];
  }
});

before

after

経緯:テンプレート機能のダイアログ中の不要なテキストを削除したい

CKEditorは、デフォルトで画像を均一幅で横並びする事が出来ません。

※以下の画像の様な配置

その為、画像を横並びに出来るにテンプレートを用意する事にしました。

テンプレート機能は完成したのですが、そのテンプレート機能を利用する際、以下の様なダイアログが表示されます。

これは、CKEditorのテンプレート機能にもともと入っている日本語ファイルから読み取られた文言です。

そもそもテンプレート機能は、全体の文章構成の雛形を出力する事を目的とした機能の様なので、現在入力中の内容と置換するオプションがデフォルトでチェックされていました。

しかし、今回は文章の中の一部分で利用する事を想定したテンプレートなので、全体と置換されてしまうと困ります。

そこで、置換オプションのチェックは外す事にしました。

※ちなみに置換オプションのデフォルトチェックを外す設定は以下の通り

templates_replaceContent: false

これでチェックを入れない限り、エディタの内容が置換されて消える事はありませんが、「現在のエディタの内容は失われます」という文言は、ユーザーに混乱を招く恐れがある為、削除する事にしました。

検証1(失敗):id/class指定でテキストを置換

まず初めに試みたのは、テキストのid(class)で該当箇所を特定して、

id/classが指定できれば、JSで置換出来ますし、:before擬似要素などを使えばCSSでも置換出来るでしょう。

しかし、これは出来ませんでした。

というのも、CKEditorのダイアログ中のテキストに適用されているidは固定では無く、classも別のダイアログと共有されているからです。

以下の様に、ページを更新したりすると、idが変わってしまい、使い物になりません・・・

検証2(失敗):公式リファレンスからダイアログのテキスト変更オプションを探す

公式リファレンスを片っ端から調査しましたが、ダイアログのテキストを変更するオプションが見当たりませんでした・・・

というかAPI関係はJS弱者の私には理解出来ない部分も多々あったので、もしかしたら上手いやり方があるかもしれません・・・

検証3(失敗):jQueryで文字列を検索して置換する

jQuery:containsを使えば、特定の文字列を持っている要素を取得出来そうだったので、試してみました。

しかし、イベント発火のタイミングが掴めず、上手いこと実装できませんでした・・・

検証4(失敗):日本語ファイルを上書きする

テンプレート機能のプラグインファイルを読み込んで、日本語ファイルを上書き出来ないか試しましたが、上手く行きませんでした・・・

ckeditor4-releases/plugins/templates at master · ckeditor/ckeditor4-releases · GitHub

以下は試したコードの一つ。

CKEDITOR.plugins.setLang("templates","ja",
    {
        selectPromptMsg:"エディターで使用するテンプレートを選択してください。\x3cbr\x3e(現在のエディタの内容は失われません!!!!!!!):",
    });

検証5(未実施):CDNやめてファイル一式をホストする

現在CDNで読み込んでますが、ファイル一式をホストして、直接ファイルを書き換える事で対応する手段も検討しました。

最終手段で考えていたので、もし他に打ち手が無ければ、これで対応していたかもしれません。

検証6(成功):コールバック設定して動的にカスタマイズ

ダイアログ(JavaScript)の生成にフックするdialogDefinition イベントにコールバックを設定し動的にカスタマイズする方法を試す事にしました。

CKEDITOR.on('dialogDefinition', function (ev) { // eslint-disable-line no-undef
  var dialogName = ev.data.name;
  var dialogDefinition = ev.data.definition;

  if (dialogName === 'templates') {
    console.log(dialogDefinition);
  }
});

ev.data.definitionにダイアログの定義データが入っていたので、デベロッパーツールで中身をしらみつぶしにチェックしていって、その値を置き換える事にしました。

そうして実装したコードが、初めに紹介したコードです。

CKEDITOR.on('dialogDefinition', function (ev) { // eslint-disable-line no-undef
  var dialogName = ev.data.name;
  var dialogDefinition = ev.data.definition;

  if (dialogName === 'templates') {
    dialogDefinition.title = '画像配置パターン';
    var selectTplText = dialogDefinition.getContents('selectTpl').elements[0].children;
    selectTplText[0].html = '<span>画像配置パターンを選択してください。</span>';
    delete selectTplText[2];
  }
});

これで、ダイアログのテキストの置き換えに成功しました!

参考情報

CKEditor 4 documentation

ckeditor4-releases/plugins/templates at master · ckeditor/ckeditor4-releases · GitHub

CKEditorをカスタマイズする - Qiita

https://blog.rmasco.com/archives/2012/02/02-074700.html