【WordPress】リスト作成ボタンを押すとliタグも追加してくれるようにする(Classic Editor)

WordPressを使い始めてから長いこと、投稿フォーム(Classic Editor)にある ul ol ボタンの動作がすごい不満でした。ストレスがマッハでハゲそう。まだハゲてないけど






デフォルトではこうなりますよね




文字列を選択して ul ボタンを押すと、





文字列の前後に <ul> と </ul> が挿入されます。





違う、そうじゃない。



理想はこうなって欲しいですよね

文字列を選択して ul ボタンを押すとこうなる。







じゃあそれ、やりましょう。



functions.phpをカスタマイズ

使っているテーマによって変わってくるのでなんとも言えませんが、僕の環境(UnderStrap + Classic Editor)ではデフォルトの代わりにこんなものを使うと実現出来ます。

変更前のコード

QTags.addButton('qt-ul','ul','\n','\n\n','','ul',3);

変更後のコード

QTags.addButton('qt-ul','ul',function() {
canvas = document.getElementById(wpActiveEditor);
text = canvas.value;
startPos = canvas.selectionStart;
endPos = canvas.selectionEnd;
scrollTop = canvas.scrollTop;
content = text.substring(startPos, endPos);
//リスト加工
content = '<ul>\n'
+ content.split(/\n/)
.map(line => '<li>' + line + '</li>')
.join('\n')
+ '\n</ul>';
//文字列挿入
canvas.value = text.substring(0, startPos) + content + text.substring(endPos, text.length);
canvas.selectionStart = startPos + content.length;
canvas.selectionEnd = startPos + content.length;
canvas.scrollTop = scrollTop;
canvas.focus();
},'','','ul',3);



これは何?

技術的な話を軽くすると、ボタンを押すとコールバック関数を実行するという仕組みを利用しています。この発想は以前から持っていたんですけど、コールバック関数内でどんな処理をしたらいいのかわからなくて実現出来てませんでした。で、あるときタグを処理する部分を実装している quicktag.js を参考にすれば良いんじゃないかと思いつき、コードを拝借してみたところ無事実装出来ました。

参考にしたのは quicktag.js 内の qt.insertContent。以下、抽出します。


qt.insertContent = function(content) {
var sel, startPos, endPos, scrollTop, text, canvas = document.getElementById(wpActiveEditor), event;
if ( !canvas ) {
return false;
}
if ( document.selection ) { //IE
canvas.focus();
sel = document.selection.createRange();
sel.text = content;
canvas.focus();
} else if ( canvas.selectionStart || canvas.selectionStart === 0 ) { // FF, WebKit, Opera
text = canvas.value;
startPos = canvas.selectionStart;
endPos = canvas.selectionEnd;
scrollTop = canvas.scrollTop;
canvas.value = text.substring(0, startPos) + content + text.substring(endPos, text.length);
canvas.selectionStart = startPos + content.length;
canvas.selectionEnd = startPos + content.length;
canvas.scrollTop = scrollTop;
canvas.focus();
} else {
canvas.value += content;
canvas.focus();
}
if ( document.createEvent ) {
event = document.createEvent( 'HTMLEvents' );
event.initEvent( 'change', false, true );
canvas.dispatchEvent( event );
} else if ( canvas.fireEvent ) {
canvas.fireEvent( 'onchange' );
}
return true;
};


ここでやっていることの中で重要なのは、選択している文字列を取得出来ていると言うことです(14行目から19行目)。方法はシンプルで、


  1. 入力欄全体のテキストを取得
  2. 選択している最初のポジションを取得
  3. 選択している最後のポジションを取得
  4. 入力欄全体のテキストから選択している部分を切り抜く


という感じ。で、そのために必要なのは canvas オブジェクトのみ。canvas オブジェクトは wpActiveEditor を利用して取得出来るようなので、別にquicktag.js じゃなくても取得出来るわけです。素敵。

あとは適当に改行で区切って1行ごとにタグを入れていって再結合すれば完成。



というわけで、長年のモヤモヤをようやく解決することが出来ました。今まで <li> と </li> タグをちまちま手作業で挿入していた時間を返して欲しい。人間あきらめたらダメですね。そこで試合終了ですからね。