ブログ記事等のエディタを実装する際はCKEditor！さらに便利でカッコよく使い易く！サンプルソースあり

# 簡単なJavaScriptの実装でエディタが作成できる！

![スクリーンショット 2016-02-12 13.06.24.png](https://qiita-image-store.s3.amazonaws.com/0/83231/1049d51d-999d-e667-a8eb-a63d35afca68.png)


## CKEditorとは

CKEditorを読み込んだ初期表示はこんな感じです。wordpressでブログ記事を書いたことがある方なら、おなじみのエディタだと思われます。

![スクリーンショット 2016-02-08 21.24.17.png](https://qiita-image-store.s3.amazonaws.com/0/83231/41e877b9-d79d-f761-ff12-0f708aa96926.png)


このCKEditor、初期状態でもかなり高機能です。例えば、下の画像のようにソースコード表示ができ、ソースコードを編集することができます。

![スクリーンショット-2016-02-08-21.24.38.png](https://qiita-image-store.s3.amazonaws.com/0/83231/079084ad-4b46-5434-b5f8-8a0d1a14239a.png)

また、ソースコード表示ではなくHTMLの表示結果を編集することもできます。(HTMLを知らない人でも編集可能)
下の画像では、見出しを選択して打ち消し線ボタンをクリックし、見出しに打ち消し線を付けています。
![スクリーンショット-2016-02-08-21.25.17.png](https://qiita-image-store.s3.amazonaws.com/0/83231/20918f21-7f4a-6ea8-8c55-ca241eb6e7ef.png)

## CKEditorの実装

CKEditor( CDN )を読み込み、scriptタグ内でdivにCKEditorをセットしています。
たったこれだけの記述で、エディタを実装することができます。また、CKEditorはJQueryを必要としません。

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
  <div id="editor"></div>
  <script src="https://cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>
  <script>
    // エディタへの設定を適用する
    CKEDITOR.replace('editor', {
      uiColor: '#EEEEEE',
      height: 400,
    });
  </script>
</body>
</html>
```

ただし、今回はこのCKEditorをさらにかっこよくし、さらに便利で使い易い状態にしていきます。最終的に作成するのは下の画像の状態になります。

![スクリーンショット 2016-02-12 12.16.02.png](https://qiita-image-store.s3.amazonaws.com/0/83231/252624b6-971c-4cde-d65c-cf34917d830c.png)


# 見た目をカッコよく

まずはCKEditorの見た目をカッコよくします。下の画像のように、エディタ自体の色を変更し、ツールバーを下側に来るようにします。また、その他の細かい設定もサンプルソースと共に解説いたします。ブログ等の記事は、文字を記述していくにつれカーソル位置が下に下がっていくので、個人的にはツールバーは下部に配置したほうが使いやすいと思っています。

![スクリーンショット 2016-02-08 21.54.31.png](https://qiita-image-store.s3.amazonaws.com/0/83231/950b1e15-1de2-2dd5-4ec6-d01c8a34f914.png)

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">

</head>
<body>
  <div id="editor"></div>
  <script src="https://cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>
  <script>
    // エディタへの設定を適用する
    CKEDITOR.replace('editor', {
      uiColor: '#EEEEEE',
      height: 400,
      // エディタ内に適用するCSS
      contentsCss: [
        "./css/sample.css",
      ],
      // スペルチェック機能OFF
      scayt_autoStartup: false,
      // Enterを押した際に改行タグを挿入
      enterMode: CKEDITOR.ENTER_BR,
      // Shift+Enterを押した際に段落タグを挿入
      shiftEnterMode: CKEDITOR.ENTER_P,
      // idやclassを指定可能にする
      allowedContent: true,
      // ツールバーを下にする
      toolbarLocation: 'bottom',
      // preコード挿入時
      format_pre: { element: 'pre', attributes: { 'class': 'code' } },
      // タグのパンくずリストを削除
      removePlugins: 'elementspath',
      // webからコピペした際でもプレーンテキストを貼り付けるようにする
      forcePasteAsPlainText: true,
      // 自動で空白を挿入しないようにする
      fillEmptyBlocks: false,
      // タブの入力を無効にする
      tabSpaces: 0,
    });
  </script>
</body>
</html>
```

contentsCssで、エディタ内で使用するCSSを適用できます。sample.cssはこの記事の最後に掲載させていただきます。

## 配置するボタンのカスタマイズ

CKEditorに配置されているボタンは初期状態だとかなり種類が多く、ユーザーからすると逆に使い辛い場合があります。また、初期状態には用意されていないボタンを独自に作成することも可能です。
下の画像のように、配置するボタンの種類や内容をカスタマイズしていきます。細かい設定などはサンプルソースと共に解説します。
また、オプションの指定などの詳細はhttp://docs.ckeditor.com/#!/api/CKEDITOR.dom.comment こちらで確認できます。(ドキュメントが若干見づらくて英語...)

### ツールバーへの配置設定

```js
  // エディタへの設定を適用する
  CKEDITOR.replace('editor', {
    // ツールバーに配置するボタンの種類を指定
    toolbar: [
      ["Source"],                                    // ソースコード表示切り替え
      ["Link", "Image", "Table", "HorizontalRule"],  // リンク、画像配置、テーブル、線
      ["Bold", "Underline", "Strike"],               // 太字、打ち消し線
      ["code"],                                      // 強調表示
      ["Recommend"],                                 // おすすめ
    ],
  });
```

codeと、Recommend以外はデフォルトで使用できるボタンになります。codeと、Recommendの内容についてはこれから作成していきます。

### ボタンのカスタマイズ(おすすめボタン)

```js
  // おすすめボタンを押した際に挿入するhtmlコード
  var recommend = '<div class="highlight"><h2 class="recommend">タイトル</h2><ol type="1"><li>項目１</li></ol></div>';

  // エディタのelement
  var editor = CKEDITOR.instances.editor;
  // エディタのプラグインが呼び出される際のcallback
  editor.on('pluginsLoaded', function(ev){
    // 各ボタンの定義
    this.ui.addButton('Recommend', {
      label: 'recommend', command: 'recommend', icon: 'images/icon_recommend.png'
    });
    this.addCommand('recommend', {
      exec: function(editor) {
        editor.insertHtml(recommend);
      }
    });
  });
```

まず、 var recommend = ... でボタン押下時にエディタ内に挿入するコードを定義します。
その次に、CKEditorの初期化時に呼ばれるcallback関数に、ボタンの定義を記述します。

this.ui.addButton ... でおすすめボタンの見た目の設定を行います。iconや、どのコマンドを実行するかを指定します。iconの画像はお好きなものを使用してください。

this.addCommand ... でボタン押下時の処理を記述します。上記コードの場合は、insertHTML関数でhtmlコードをエディタ内に挿入しているだけです。

おすすめボタンが追加されました。
![スクリーンショット-2016-02-12-11.48.42.png](https://qiita-image-store.s3.amazonaws.com/0/83231/75d66548-acf5-1370-d39c-fd1b2a81482a.png)



### ボタンのカスタマイズ(強調表示ボタン)

続いて、強調表示ボタンを追加します。強調表示ボタンは、エディタ上で選択した文字列の範囲を強調します。さきほど追加したおすすめボタンと追記する内容についてはほぼ同じです。

```js
  // 強調表示
  var code = '<code>強調</code>';

  // エディタのelement
  var editor = CKEDITOR.instances.editor;
  // エディタのプラグインが呼び出される際のcallback
  editor.on('pluginsLoaded', function(ev){
    // 各ボタンの定義
    this.ui.addButton('code', {
      label: 'code', command: 'code', icon: 'images/code.png'
    });
    this.addCommand('code', {
      exec: function(editor) {
        editor.insertHtml(replace_tag_inner(code, "強調"));
      }
    });
  });
```

this.addCommand... おすすめボタン作成時は、単純にinsertHTMLを行っていましたが、今回は選択範囲を強調表示させたいので、エディタ内で選択されている範囲を取得し、範囲内の文字列を強調表示に置き換えた上でinsertHTMLを行わなければいけません。そこで、replace_tag_inner()という関数を作成します。

```js
  // タグ内にエディタで選択中の文字列を挿入する
  function replace_tag_inner(tag, str) {
    var result = tag;
    var selected_str = editor.getSelection();
    // エディタ内で選択中の文字列が存在する場合
    if (selected_str && selected_str.getNative() != '') {
      result = result.replace(str, selected_str.getNative());
    }
    return result;
  }
```

上記コードは、エディタ内での選択範囲をeditor.getSelection()で取得し、強調表示用のタグに置き換えています。

強調表示ボタンが追加されました。
![スクリーンショット-2016-02-12-12.01.57.png](https://qiita-image-store.s3.amazonaws.com/0/83231/67942178-c6fc-6aac-ac49-c1543dc0351f.png)

このように、ボタンを追加していくことでより便利な機能を追加することができます。

## まとめ & サンプル

以上が今回ご紹介するカスタマイズ内容になります。
下記のソースが今回の内容をまとめたものです。

```html:sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">

</head>
<body>
  <div id="editor"></div>
  <script src="https://cdn.ckeditor.com/4.5.6/standard/ckeditor.js"></script>
  <script>
    // エディタへの設定を適用する
    CKEDITOR.replace('editor', {
      uiColor: '#EEEEEE',
      height: 400,
      // エディタ内で使用するCSS
      contentsCss: [
        "./css/sample.css",
      ],
      toolbar: [
        ["Source"],
        ["Link", "Image", "Table", "HorizontalRule"],
        ["Bold", "Underline", "Strike"],
        ["FontSize", "TextColor"],
        ["code"],
        ["Recommend"],
      ],
      // スペルチェック機能OFF
      scayt_autoStartup: false,
      // Enterを押した際に改行タグを挿入
      enterMode: CKEDITOR.ENTER_BR,
      // Shift+Enterを押した際に段落タグを挿入
      shiftEnterMode: CKEDITOR.ENTER_P,
      // idやclassを指定可能にする
      allowedContent: true,
      // ツールバーを下にする
      toolbarLocation: 'bottom',
      // preコード挿入時
      format_pre: { element: 'pre', attributes: { 'class': 'code' } },
      // タグのパンくずリストを削除
      removePlugins: 'elementspath',
      // webからコピペした際でもプレーンテキストを貼り付けるようにする
      forcePasteAsPlainText: true,
      // 自動で空白を挿入しないようにする
      fillEmptyBlocks: false,
      // タブの入力を無効にする
      tabSpaces: 0,
    });
  
    // おすすめボタンを押した際に挿入するhtmlコード
    var recommend = '<div class="highlight"><h2 class="recommend">タイトル</h2><ol type="1"><li>項目１</li></ol></div>';
    // 強調する文字
    var code = '<code>強調</code>';
    // エディタのelement
    var editor = CKEDITOR.instances.editor;
  
    // エディタのプラグインが呼び出される際のcallback
    editor.on('pluginsLoaded', function(ev){
      // 各ボタンの定義
      this.ui.addButton('Recommend', {
        label: 'recommend', command: 'recommend', icon: 'images/recommend.png'
      });
      this.ui.addButton('code', {
        label: 'code', command: 'code', icon: 'images/code.png'
      });
      this.addCommand('recommend', {
        exec: function(editor) {
          editor.insertHtml(recommend);
        }
      });
      this.addCommand('code', {
        exec: function(editor) {
          editor.insertHtml(replace_tag_inner(code, "強調"));
        }
      });
    });
  
    // タグ内にエディタで選択中の文字列を挿入する
    function replace_tag_inner(tag, str) {
      var result = tag;
      var selected_str = editor.getSelection();
      // エディタ内で選択中の文字列が存在する場合
      if (selected_str && selected_str.getNative() != '') {
        result = result.replace(str, selected_str.getNative());
      }
      return result;
    }
  </script>
</body>
</html>
```


```css:sample.css
.highlight {
    width: auto;
    background-color: #f7f3f2;
    border-radius: 3px;
    padding: 15px;
    line-height: 1.15em;
    word-wrap: break-word;
    margin-bottom: 10px
}

.highlight h2 {
    color: #000;
    font-size: 16px;
    font-weight: bold;
    margin: 0;
    margin-bottom: 15px;
    line-height: 1.5em;
    padding: 10px;
    padding-left: 0
}

.highlight h2.recommend:before {
    content: "オススメ";
    color: #fff;
    font-size: 12px;
    background-color: #ff9900;
    border-radius: 50%;
    padding: 20px 5px;
    margin-right: 10px
}

code {
    padding: 2px 4px;
    color: #d14;
    white-space: nowrap;
    background-color: #f7f7f9;
    border: 1px solid #e1e1e8;
    font-size: 1em;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
    font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
}
```

以上になります。