Movable Type のリッチエディタ(TinyMCE)に文字数カウント機能を付ける

本文フィールドで文字カウント - MTQ | Movable Type ユーザーコミュニティ という質問を見つけましたので、Movable Type の本文欄で使われているリッチエディタ(TinyMCE)に文字数カウント機能を追加してみます。

文字数を表示するための要素を追加

下記のコードで文字数を表示するためのコードを追加します。

jQuery(function($){
    var l = $('#editor-input-content').val().replace(/<.*?>|\n/g, '').length;
    var statusHTML = '<span>文字数 : <span id="current-length">' + l + '</span> / </span>';
    $('#field-convert_breaks').prepend(statusHTML);
});

リッチテキストで入力された実際のテキストは $('#editor-input-content') に入っていますので(リッチテキスト保存後)、この値を取得して現在の文字数を表示します。

TinyMCE を拡張して文字数を取得

次に、TinyMEC を拡張して、onKeyUp イベントで文字数を取得して、追加した HTML に文字数を入れていきます。

var config   = MT.Editor.TinyMCE.config;
config.setup = function(ed) {
        ed.onKeyUp.add(function(ed, e) {
            document.getElementById('current-length').innerHTML = ed.getBody().textContent.length;
        });
};

上記の ed.onKeyUp.add でキーが押されて上がったタイミングで文字数を取得して表示しています。

onKeyUp の他にも onKeyDownonKeyPress もありますが、 onKeyPress は日本語入力時やエンターで確定したときには呼ばれないようです。

管理画面に反映させる

このコード全体を、管理画面の js_include 変数に追加します。

<mt:setvarblock name="js_include" append="1">
<script>
jQuery(function($){
    var l = $('#editor-input-content').val().replace(/<.*?>|\n/g, '').length;
    var statusHTML = '<span>文字数 : <span id="current-length">' + l + '</span> / </span>';
    $('#field-convert_breaks').prepend(statusHTML);
});
var config   = MT.Editor.TinyMCE.config;
config.setup = function(ed) {
        ed.onKeyUp.add(function(ed, e) {
            document.getElementById('current-length').innerHTML = ed.getBody().textContent.length;
        });
};
</script>
</mt:setvarblock>

これを管理画面に反映させるには、alt-tmpl を使う方法と MTAppjQuery を使う方法(オススメ)があります。

alt-tmpl を使う場合

alt-tmpl を使う場合は、mt/tmpl/cms/edit_entry.tmpl の中の、

<mt:include name="include/header.tmpl" id="header_include">

の手前に上記のコードを挿入します。

MTAppjQuery プラグインを使う場合

MTAppjQuery があれば、下記のように全体を mt:If で囲って記事編集画面にだけ適用するようにして、反映させたいウェブサイト/ブログの MTAppjQuery プラグイン設定の「変数 js_include に追加(の直前)」欄に入力すればOKです。

<mt:If name="mtappVars" key="screen_id" eq="edit-entry">
<mt:setvarblock name="js_include" append="1">
<script>
jQuery(function($){
    var l = $('#editor-input-content').val().replace(/<.*?>|\n/g, '').length;
    var statusHTML = '<span>文字数 : <span id="current-length">' + l + '</span> / </span>';
    $('#field-convert_breaks').prepend(statusHTML);
});
var config   = MT.Editor.TinyMCE.config;
config.setup = function(ed) {
        ed.onKeyUp.add(function(ed, e) {
            document.getElementById('current-length').innerHTML = ed.getBody().textContent.length;
        });
};
</script>
</mt:setvarblock>
</mt:If>

リッチエディタを適用しているフィールドを特定する(追記:2015/04/08)

下記のようなご指摘をいただきました。

ひとつ問題がありそうです。複数のリッチテキストフィールドがMTAppApplyTinyMCEなどで複数適応している場合、入力時に他のリッチテキストフィールドと文字数が干渉してしまうようです。

今回の方法では、 MT.Editor.TinyMCE.config に設定しているので、複数のフィールドでリッチエディタを適用している場合はご指摘のように文字数が干渉してしまいます。「複数のフィールドで」と言いましたが、そもそもデフォルトでは本文欄と続き欄の2箇所で使用しているので干渉してしまいますね。

ちなみに、「MTAppApplyTinyMCE」というのは、概要欄やテキスト(複数行)のカスタムフィールドを簡単にリッチテキストエディタに変更することができる MTAppjQuery プラグインのメソッドです。

そこで、onKeyUp イベントの中で、下記のように適用されているフィールドによって処理を分岐することができます。

ed.onKeyUp.add(function(ed, e) {
    if (ed.id === "editor-input-content") {
        document.getElementById('current-length').innerHTML = ed.getBody().textContent.length;
    }
});

このように ed.id でエディタが適用されているフィールドの ID を取得することができます。本文欄であれば editor-input-content で、続き欄であれば editor-input-extended となります。

これを利用して、文字数を表示する要素をフィールドごとに用意しておけば良いでしょう(ここではその方法は割愛します)。

以上です。

  • このエントリーをはてなブックマークに追加
Just a second...