Help us understand the problem. What is going on with this article?

IEでテキストエリアの文字列をタグで囲む

More than 3 years have passed since last update.

ブログ投稿画面などのエディタで、選択文字列を<strong>強調</strong>とかって囲んだりする機能がありますが、それをIEでやるときの話です。

例えばこのはてなブログの見出しボタンとかもそうですね。
h1とかで囲んでくれます。
00c5d2d0b9eb143833996b448b704c9c.png
BとかIとかもです。

textareaの選択範囲を取得し、前後に文字列を挿入する

検索すると参考サイトとして上のようなページがあるのですが、2007年の記事でして、しかもうまく動きません。
2.png
「筍子」を押してstrongボタンを押すと、その後ろの「。学」が囲まれちゃうようです。

テキストエリアの1行目だと動いていて、2行目、3行目と1文字ずつずれてしまうようです。
ということは改行コードですね。

テキストエリアの選択範囲の位置を特定する

そこで検索してこの記事を見つけました。2006年の記事で、IEに対比するものとしてNNとか書いてあります。
NNに続くMozilla系だとテキストエリアの改行コードが¥nなんですが、IEだと¥r¥nになっちゃうようです。

ということで、1件目の記事のコードを2件目の記事を参考に書き換えてみました。
変更箇所が下記になります。選択文字列の地点を取るgetAreaRangeメソッドの、if(isIE)の辺りです。

enclose.js
...
            obj.focus();
            var range = document.selection.createRange();
            var len = range.text.replace(/\r/g, "").length;
            var clone = range.duplicate();

            clone.moveToElementText(obj);

            var all_len = clone.text.replace(/\r/g, "").length;
            clone.setEndPoint( 'StartToStart', range );

            var s = all_len - clone.text.replace(/\r/g, "").length;

            pos.start = s;
            pos.end = s + len;
...

変更点としては、text.lengthを全て、text.replace(/\r/g, "").lengthにしたのと、
setEndPoint("EndToEnd" をsetEndPoint("StartToStart" にしました。

デモページを作ったところ、正常に選択範囲が囲まれました。
Untitled.png

デモのHTML全文は下記のようになります。

demo.html
<html>
<head>
<script type="text/javascript">
window.onload = function() {

    var enc = document.getElementById("enclose");
    enc.onclick = function() {
        surroundHTML("div", "txt");
    };



    function getAreaRange(obj) {
        var pos = new Object();

        if (isIE) {
            obj.focus();
            var range = document.selection.createRange();
            var len = range.text.replace(/\r/g, "").length;
            var clone = range.duplicate();

            clone.moveToElementText(obj);

            var all_len = clone.text.replace(/\r/g, "").length;
            clone.setEndPoint( 'StartToStart', range );

            var s = all_len - clone.text.replace(/\r/g, "").length;

            pos.start = s;
            pos.end = s + len;

        }

        else if(window.getSelection()) {
            pos.start = obj.selectionStart;
            pos.end = obj.selectionEnd;
        }

        return pos;
    }
    var isIE = (navigator.appName.toLowerCase().indexOf('internet explorer')+1?1:0);

    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;
        }
    }

}
</script>
</head>
<body>
<div>
<input type="button" id="enclose" value="enclose" />
</div>

<div>
<textarea id="txt" rows="20" cols="100">
即興ソング
カメルーン
ブランチ
発送商品の場合、良品と交換いたします。不良品の返品にかかる送料は、弊社が負担いたします。ただし、良品在庫のない場合及び数量限定品の場合については個別にご相談させていただきます。 デジタルコンテンツ(PDF版書籍等)の場合は、再ダウンロード方法についてご案内いたします。 
</textarea>
</div>


</body>
</html>
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away