Medium Editorでフォントカラーを変更できる仕様にカスタマイズしてみた

##はじめに
Railsに導入したMediumエディターにフォントカラーの編集機能を追加する方法を自分の備忘録として書いておきます。


##環境
Rails6 (6.0.1)
ruby 2.7.0
jQuery(3.4.1)をインストール済み


##参考
[medium-editor support for font color?](https://github.com/yabwe/medium-editor/issues/523)
[https://github.com/Olgagr/vanilla-color-picker](https://github.com/Olgagr/vanilla-color-picker)


##MediumEditorとは？
有名ブログサービスのMediumで使われているWYSIWYGエディターです。Gemのmedium-editor-railsをインストールすることで簡単にMediumエディターをRailsアプリに導入することができます。


##MediumEditorを適用させる
テキストエリアにeditableというクラスを付与させた上で、下記のスクリプトを実行するとMedium Editorが適用されます。

```javascript
  var editor = new MediumEditor('.editable', {
    // placeholder の設定
    placeholder: {
      text: 'テキストを入力してください',
      hideOnClick: true
    }
  });

  $('.editable').mediumInsert({
    editor: editor
  });
```
※RailsにMediumEditorを導入する際は[こちらの記事](https://qiita.com/sayama0402/items/8c0ecac2bca3a76625ac)を参考にしました。

##フォントカラーの編集機能を追加する方法
[vanilla-color-picker](https://github.com/Olgagr/vanilla-color-picker)を利用して、機能拡張を行います。

ディレクトリ構成は以下になります。

###ディレクトリ構成
　app/
　　├ 〜
　　└ javascript/
　　　 ├ packs/
　　　 │　　└ application.js
　　　 ├ vanilla-color-picker.js
　　　 ├ color_picker.js
　　　 └ medium_editor.js


### 1. vanilla-color-picker.jsをjavascriptディレクトリの配下に置く
ファイルは[こちらのファイル](https://github.com/Olgagr/vanilla-color-picker/tree/master/dist)を利用しました。

### 2. color-picker.jsをjavascriptディレクトリに作成
このファイルでColorPickerExtension()を下記のように定義します。

```javascript:color-picker.js
(function () {

    function ColorPickerExtension() {
        this.button = document.createElement('button');
        this.button.classList.add('medium-editor-action');
        this.button.classList.add('editor-color-picker');
        this.button.title = '文字色'
        this.button.innerHTML = '<i class="fa fa-paint-brush"></i>';
        this.button.onclick = this.onClick.bind(this);
    }

    /**
     * onClick
     * The click event handler that calls `insertHtmlAtCaret` method.
     *
     * @name onClick
     * @function
     */
    ColorPickerExtension.prototype.onClick = function (e) {
        e.preventDefault();
        e.stopPropagation();
        this.selectionState = this.base.exportSelection();
        // If no text selected, stop here.
        if (this.selectionState && (this.selectionState.end - this.selectionState.start === 0)) {
          return;
        }

        // 選択できるフォントカラーを指定します
        var pickerColors = [
          "#1abc9c",
          "#2ecc71",
          "#3498db",
          "#9b59b6",
          "#34495e",
          "#16a085",
          "#27ae60",
          "#2980b9",
          "#8e44ad",
          "#2c3e50",
          "#f1c40f",
          "#e67e22",
          "#e74c3c",
          "#bdc3c7",
          "#95a5a6",
          "#f39c12"
        ];

        var picker = vanillaColorPicker(this.document.querySelector(".medium-editor-toolbar-active .editor-color-picker").parentNode);
        picker.set("customColors", pickerColors);
        picker.set("positionOnTop");
        picker.openPicker();
        picker.on("colorChosen", function (color) {
          this.base.importSelection(this.selectionState);
          this.document.execCommand("styleWithCSS", false, true);
          this.document.execCommand("foreColor", false, color);
        }.bind(this));
    };

    /**
     * getButton
     * This function is called by the Medium Editor and returns the button that is
     * added in the toolbar
     *
     * @name getButton
     * @function
     * @return {HTMLButtonElement} The button that is attached in the Medium Editor
     * toolbar
     */
    ColorPickerExtension.prototype.getButton = function () {
        return this.button;
    };


    // windowオブジェクトに定義します
    window.ColorPickerExtension = ColorPickerExtension;
})();

```

### 3. MediumEditorのextensionsオプションにColorPickerExtension()を追加
2で定義したColorPickerExtension()をextensionsオプションに追加します。

```javascript:
  extensions: {
      "colorPicker": new ColorPickerExtension()
    }
```
これで"colorPicker"をtoolbarのbuttonsオプションに指定してあげるとMedium Editorでフォントカラーを編集できるボタンを表示させることができます。

```javascript:
  toolbar: {
        buttons: ['bold', 'italic', 'underline', 'anchor', 'colorPicker', 'indent', 'outdent'],
        diffLeft: 25,
        diffTop: -10,
    }
```

ファイル全体の内容は以下

```javascript:medium_editor.js
  var editor = new MediumEditor('.editable', {
    // placeholder の設定
    placeholder: {
      text: 'テキストを入力してください',
      hideOnClick: true
    },
    toolbar: {
        buttons: ['bold', 'italic', 'underline', 'anchor', 'colorPicker', 'indent', 'outdent'],
        diffLeft: 25,
        diffTop: -10,
    },
    extensions: {
      "colorPicker": new ColorPickerExtension()
    }
  });

  $('.editable').mediumInsert({
    editor: editor
  });
```

###4.application.jsを編集
この状態では、vanilla-color-picker.jsとcolor-picker.jsが読み込まれていない状態なのでapplication.jsに追記します。

```javascript:application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("jquery")

//追加 ----
require("vanilla-color-picker.js")
require("color-picker.js")
// -------

require("medium_editor.js")


```

##完成

これでMedium Editorでフォントカラーを編集できるようになります。
![guide6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151361/0bf343a2-37d6-2eff-a75d-1bed28c8ec97.gif)