Facebookで人物を補完すると、その人物名の周りに枠が表示されて強調されますよね(gif画像参照)。
これのやり方を解説します。
TL;DR
textareaの強調表示は、textareaを透明にして後ろにいい感じの背景を設置してるだけ
textareaの中にDOMを入れても表示されない
パッと考えるとtextareaの中にDOMツリーを入れるとそれが表示されるんじゃないか、と思うかも知れません
<textarea><span>1</span></textarea>
が、ぜんぜんそんなことは無くて、そのまま文字列が表示されてしまいます。
ご存知のようにtextareaやinputは、他の要素のように子要素を表示するのではなく、自身のvalue属性の値を画面に表示する働きをします。value属性は文字列を格納するためのものなのでDOMを入れられないわけですね。
強調用のDOMを重ねあわせる
textareaにはDOMをそのまま入れられないので、仕方がなく周りに設置したDOMの位置を微調整して重ねあわせることでtextareaが強調されているかのように見せかけているわけです。
このとき問題になるのがtextareaと重ねあわせるDOMのz軸方向の位置関係です。textareaより手前にあるとtextareaを選択できなくなってしまします。一方でtextareaより奥にあると表示されません。
さてどうしたら良いのでしょう?
background-color: transparentが肝
textareaの背景色を透明にして、後ろにあるDOMが表示されるようにすればよさそうですね。つまりtextareaが background-color: transparent;
であればよいわけです。
いい感じの場所に背景色をつけるにはどうすればいいの?
もう一つ考えなければならないのが、どこに背景を設置するかです。やり方はいろいろ考えられますが、後述するサンプル実装の場合は、textareaの文字列の背後に全く同じ透明な文字列を設置して、該当箇所を強調させています。全く同じ文字列を全く同じように背後に置いてあるので、位置がピタリと合う訳ですね。他にもやり方はありそうなので考えてみてください。
サンプル
で、試しに作ってみました。
このプラグインは正規表現で指定された文字列に背景色を付けるシンプルなものです。
非常にシンプルなので、先日公開したtextareaに補完機能をつけるプラグインとも簡単に結合することが可能です。プラガブル万歳\(^o^)/
textareaを使うと背景色を変えるくらいしか強調手段がない
上記のサンプルページを表示してみた人は気がついたかも知れませんが、背景色を付ける以外の強調方法を使えません。例えば文字の色を変えたり、イタリックにしたり、太さを変えたり、大きさを変えたりしたくてもできないのです。
理由はtextareaを使っていることです。あくまでも表示されている文字列はtextarea由来のものであり、こいつらの一部の色を変えたり、イタリックにしたりすることができないのは最初に見た通りです(てか、それができるならこんな回りくどいことをしなくてもいいわけで)。
contentEditableを使えばなんとかなる?
contentEditableは使えないのか?と思う向きもあるかと思います。たしかにその通りでcontentEditableを使うこともできるかも知れません。こちらを使えば文字列の大きさも好き勝手に変えられるので表現力は上です。
が、いかんせん面倒なのでやってない+contentEditable内でのカーソル位置の制御が難しい(JavaScriptから調整不可?)なので、僕は諦めた次第です。
まとめ
textareaの強調表示は、textareaを透明にして後ろにいい感じの背景を設置してるだけ