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

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

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

違う、そうじゃない。
理想はこうなって欲しいですよね
文字列を選択して ul ボタンを押すとこうなる。
じゃあそれ、やりましょう。
functions.phpをカスタマイズ
使っているテーマによって変わってくるのでなんとも言えませんが、僕の環境(UnderStrap + Classic Editor)ではデフォルトの代わりにこんなものを使うと実現出来ます。変更前のコード
QTags.addButton('qt-ul','ul','\n','\n\n','','ul',3);
変更後のコード
これは何?
技術的な話を軽くすると、ボタンを押すとコールバック関数を実行するという仕組みを利用しています。この発想は以前から持っていたんですけど、コールバック関数内でどんな処理をしたらいいのかわからなくて実現出来てませんでした。で、あるときタグを処理する部分を実装しているquicktag.js
を参考にすれば良いんじゃないかと思いつき、コードを拝借してみたところ無事実装出来ました。参考にしたのは
quicktag.js
内の qt.insertContent
。以下、抽出します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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行目)。方法はシンプルで、
- 入力欄全体のテキストを取得
- 選択している最初のポジションを取得
- 選択している最後のポジションを取得
- 入力欄全体のテキストから選択している部分を切り抜く
という感じ。で、そのために必要なのは
canvas
オブジェクトのみ。canvas
オブジェクトは wpActiveEditor
を利用して取得出来るようなので、別にquicktag.js
じゃなくても取得出来るわけです。素敵。あとは適当に改行で区切って1行ごとにタグを入れていって再結合すれば完成。
というわけで、長年のモヤモヤをようやく解決することが出来ました。今まで <li> と </li> タグをちまちま手作業で挿入していた時間を返して欲しい。人間あきらめたらダメですね。そこで試合終了ですからね。
