textareaの選択範囲を取得し、前後に文字列を挿入する
2007–03–23
textareaの中で選択した文字列の前後に、任意の文字列を挿入するJavascript。流れとしては、まず選択領域の始点と終点の位置を取得し、その境界を基準にしてtextareaの文字列全体を分割。そして加工して組みなおす。
始点と終点の位置は、Mozillaおよび(最近の)Opera/Safariでは容易に取得できる。問題はIE。IEのTextRangeオブジェクトは、後のコンテクストを見て処理を行うことが難しいため、特にtextarea内の文字列を操作したい場合は厄介です。
逆に言えば、始点と終点の位置さえ判ればなんとかなるので、いろいろ試してみてなんとか形に出来ました。
Sample
memo: サンプルのテキストは、以前書いた記事「環境は人を造るか?」より抜粋。
Script
function getAreaRange(obj) {var pos = new Object();if (isIE) {obj.focus();var range = document.selection.createRange();var clone = range.duplicate();clone.moveToElementText(obj);clone.setEndPoint( 'EndToEnd', range );pos.start = clone.text.length - range.text.length;pos.end = clone.text.length - range.text.length + range.text.length;}else if(window.getSelection()) {pos.start = obj.selectionStart;pos.end = obj.selectionEnd;}return pos;// alert(pos.start + "," + pos.end);}var isIE = (navigator.appName.toLowerCase().indexOf('internet explorer')+1?1:0);
ここが要。選択領域の位置を取得している部分。既存の選択領域とは別の選択領域を用意し、新しい選択領域でtextareaを選択。始点あるいは終点を操作し、2つの選択領域の文字数をカウントすることで位置を割り出す。
note: 「clone.setEndPoint( 'EndToEnd', range );」で、「cloneの終点をrangeの終点に合わせる」の意。
function surroundHTML(tag, obj) {var target = document.getElementById(obj);var pos = getAreaRange(target);var val = target.value;var range = val.slice(pos.start, pos.end);var beforeNode = val.slice(0, pos.start);var afterNode = val.slice(pos.end);var insertNode;if (range || pos.start != pos.end) {insertNode = '<' + tag + '>' + range + '</' + tag + '>';target.value = beforeNode + insertNode + afterNode;}else if (pos.start == pos.end) {insertNode = '<' + tag + '>' + '</' + tag + '>';target.value = beforeNode + insertNode + afterNode;}}
境界の座標が判れば、後は「分割 → 追加 → 再統合」の流れでOK。この場合は選択領域だけでなく、まだ選択していない状態でもキャレット(文字の入力位置を示すポインタ)の位置に挿入できるようになっている ...が、この操作は関数getAreaRange()にて「obj.focus()」していないとIEでは巧くいかなかったりする。注意。
参照: Experts Exchange, IE - textarea caret position
22 Comments
お役に立てて良かったです!
コメント thx! 2008–01–12 16:51
TinyMCE等のリッチテキストエディタでいろいろやろうと考えてましたが、もっと軽量で
スタイリッシュなものをと望んでいたところ、このサイトを見つけました。
これをもとに、いいものを作りたいと思います。本当にありがとうございました。 2008–05–29 13:00
どうぞ心ゆくまで使い倒してやってください^^b 2008–06–02 20:45
こちらのスクリプトがとても参考になりました。
ありがとうございます。 2008–06–26 15:40
いや、意外と需要あるんですね、コレ。
モチベ上がってきた...! 2008–06–28 05:07
使わせてもらいます、本当にありがとうございました。 2008–07–12 23:40
var target = document.getElementById(obj);
この要素取得については別の関数にしたかったので、
勝手ながら若干改造しました^^ 2008–08–02 20:30
ありがとうございます。
早速、使わせて頂きます。 2008–10–24 22:48
ありがとうございました。 2008–12–16 15:35
ありがとうございました。 2009–01–05 16:49
参考にさせていただきます。
どうもありがとうございます。 2009–02–28 22:18
これを参考させていただきますね。
ありがとうございました。 2009–06–02 14:24
本当に困っていたので助かりました^-^b 2009–06–22 17:19
心より感謝です…。ありがとうございます! 2009–09–17 07:23
個人または家族で使える自宅用のWebポータルシステム「MyHome Portal」をオープンソースとして公開しています。
このMyHome Portalのカレンダーのスケジュール入力画面で、スクリプトを利用させていただきました。
http://ok2nd.blog87.fc2.com/blog-entry-129.html
Chrome、Safariでtextarea内の文字列選択がうまくいかない問題がやっと解決できました。
ありがとうございました。 2009–10–03 07:32
助かりました。ありがとうございました。 2010–02–15 20:09