LoginSignup
22
30

More than 5 years have passed since last update.

CKEditorをカスタマイズする

Posted at

リッチな WYSIWYG エディタで CKEditor をカスタマイズする。

前提条件

  • Rails 5.x
  • CKEditor の v4.2.4 を使用

以下、JavaScriptの処理は Rails に限らず使用できる。

不要なボタンを消す

デフォルトの editorConfig を上書きすることで表示項目をカスタマイズできる。

次の例は最低限 WYSIWYG に必要な機能だけ残し、エディタの高さを 380px 固定にした例。

app/assets/javascripts/ckeditor/config.js
CKEDITOR.editorConfig = function (config) {
    config.toolbar_mini = [
        {
            name: 'paragraph',
            groups: ['list', 'indent', 'blocks', 'align', 'bidi'],
            items: [
                'NumberedList', 'BulletedList',
                '-',
                'Outdent', 'Indent',
                '-',
                'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'
            ]
        },
        {
            name: 'links',
            items: [
                'Link', 'Unlink'
            ]
        },
        {
            name: 'basicstyles',
            groups: ['basicstyles', 'cleanup'],
            items: [
                'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript',
                '-',
                'RemoveFormat'
            ]
        },
        {
            name: 'insert',
            items: [
                'Image', 'Table', 'HorizontalRule'
            ]
        }
    ];

    // toolbar_mini が読み込まれる
    config.toolbar = "mini";

    // 高さを指定
    config.height = '380px';
};

image.png

i18n

locale ファイルを追加することでボタンなどの表示を i18n 対応できる。
しかし locale ファイルが適用されない箇所もあり、それは後述する。

config/locales/ja.ckeditor.yml
ja:
  ckeditor:
    confirm_delete: 'ファイルを削除してもよろしいですか?'
    buttons:
      cancel: 'キャンセル'
      upload: 'アップロード'
      delete: '削除'
      next: '次へ'
    dialog:
      title: '画像'

リンク追加ダイアログをカスタマイズ

Link ボタンをクリックしたときに表示されるダイアログをカスタマイズする。
ダイアログはボタンがクリックされたときに JavaScript で生成される。その生成を hook する dialogDefinition イベントにコールバックを設定し動的にカスタマイズする必要がある。

image.png

ダイアログを取得し、そのタブ内の任意のフィールドを書き換えている。.getContents で要素を取得したり、 .removeContents で不要な要素を削除できる。
日本語をハードコーディングしているところは、i18n-jsとか使って i18n 対応した方がよい。

app/assets/javascripts/ckeditor/config.js
CKEDITOR.on('dialogDefinition', function (ev) {
    var dialogName = ev.data.name;
    var dialogDefinition = ev.data.definition;

    if (dialogName === 'link') {
        var infoTab = dialogDefinition.getContents('info');
        if (infoTab) {
            var urlField = infoTab.get('url');
            urlField['default'] = 'www.example.com';
        }

        if (dialogDefinition.getContents('advanced')) dialogDefinition.removeContents('advanced');
    }
}

画像選択ダイアログをカスタマイズ

リンクと同様に JavaScript でカスタマイズする。

image.png

app/assets/javascripts/ckeditor/config.js
CKEDITOR.on('dialogDefinition', function (ev) {
    var dialogName = ev.data.name;
    var dialogDefinition = ev.data.definition;

    •••

    if (dialogName === 'image') {
        var uploadTab = dialogDefinition.getContents('Upload');
        if (uploadTab) {
            var upload = uploadTab.get('upload');
            if (upload) upload.label = '画像を選択してください';

            var uploadButton = uploadTab.get('uploadButton');
            if (uploadButton) uploadButton.label = 'アップロード';
        }

        var infoTab = dialogDefinition.getContents('info');
        if (infoTab) {
            infoTab.remove('txtAlt');
            infoTab.get('txtUrl')['hidden'] = true;
            infoTab.remove('txtHSpace');
            infoTab.remove('txtVSpace');
            infoTab.remove('txtBorder');
            infoTab.remove('cmbAlign');

            var browse = infoTab.get('browse');
            if (browse) browse.label = 'アップロード済みの画像を選択';
        }

        // remove unnecessary tabs
        if (dialogDefinition.getContents('Link')) dialogDefinition.removeContents('Link');
        if (dialogDefinition.getContents('advanced')) dialogDefinition.removeContents('advanced');
    }
});

画像のサイズ指定方法を変更

デフォルトだと画像のサイズ指定が、インラインの style タグで記述される。
<img>height width 属性で指定したい場合は次の設定をする。

app/assets/javascripts/ckeditor/config.js
CKEDITOR.editorConfig = function (config) {
    •••

    // 画像のサイズ指定をstyleタグではなく,width,height属性で設定
    config.disallowedContent = 'img{width,height}';
    config.extraAllowedContent = 'img[width,height]';
};

Turbolinks と組み合わせる

turbolinks:load イベント内で、<%= f.cktext_area :content %> によってレンダリングされた全ての HTML を初期化する。

app/assets/javascripts/ckeditor/index.js
//= require ckeditor/init.js.erb
//= require ./config

$(document).on('turbolinks:load', function () {
    $('.ckeditor').each(function () {
        CKEDITOR.replace($(this).attr('id'))
    });
});

Form の Dirty Check をする

CKEditor の form と、それ以外を両方 Dirty Check するコードを示す。

まず CKEDITORhasDirtyForm メソッドを追加する。

app/assets/javascripts/ckeditor/index.js
//= require ckeditor/init.js.erb
//= require ./config

CKEDITOR.hasDirtyForm = function () {
    var editors = this.instances;
    return Object.keys(editors).some(function (key) {
        return editors[key].checkDirty();
    });
};

turbolinks:load で Dirty Check を初期化する。

Form が Dirty で、まだ Submit されていない場合にのみ confirm が表示されるようになる。

app/assets/javascripts/dirty-forms.js
$(window)
    .on('turbolinks:load', function () {
        if (!window.app) window.app = {};
        window.app.formDirty = false;
        window.app.formSubmit = false;
        window.app.dirtyMessage = '保存していない内容が失われますが、よろしいですか';

        $(':input').change(function () {
            if (!window.app.formDirty) window.app.formDirty = true;
        });
        $('form').submit(function () {
            window.app.formSubmit = true;
        });
    })
    .on("page:before-change turbolinks:before-visit", function () {
        if (window.app.formDirty || CKEDITOR.hasDirtyForm()) {
            return confirm(window.app.dirtyMessage);
        }
    })
    .bind("beforeunload", function (event) {
        if (!window.app.formSubmit &&
            (window.app.formDirty || CKEDITOR.hasDirtyForm())) {
            event.returnValue = window.app.dirtyMessage;
            return event.returnValue;
        }
    });
22
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
30