IE에서 텍스트 영역 문자열을 태그로 둘러싸기

16785 단어 자바스크립트
블로그 투고 화면등의 에디터로, 선택 문자열을 <strong>強調</strong> 라고 해 둘러싸는 기능이 있습니다만, 그것을 IE로 할 때의 이야기입니다.

예를 들어, 이 하테나 블로그의 제목 버튼일지도 모르겠네요.
h1 등으로 둘러싸고 있습니다.

B라든지 I라든지입니다.

textarea의 선택 범위를 취득해, 전후에 캐릭터 라인을 삽입한다

검색하면 참고 사이트로서 위와 같은 페이지가 있습니다만, 2007년의 기사로 해, 밖에 잘 움직이지 않습니다.

「순간」을 누르고 strong 버튼을 누르면, 그 뒤의 「.학」이 둘러싸여 버리는 것 같습니다.

텍스트 영역의 1행째라고 움직이고 있어, 2행째, 3행째와 1문자씩 어긋나 버리는 것 같습니다.
라는 것은 개행 코드군요.

텍스트 영역의 선택 영역의 위치 지정

그래서 검색하여이 기사를 찾았습니다. 2006년 기사에서 IE에 대비하는 것으로 NN이라든지 쓰고 있습니다.
NN에 이어 Mozilla계라고 텍스트 에리어의 개행 코드가 ¥n입니다만, IE라면 ¥r¥n이 되어 버리는 것 같습니다.

그래서 첫 번째 기사의 코드를 두 번째 기사를 참고로 다시 작성해 보았습니다.
변경 개소가 아래와 같습니다. 선택 문자열의 지점을 취하는 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"로 했습니다.)

데모 페이지를 만들었는데, 성공적으로 선택 범위가 둘러싸였습니다.


데모의 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>

좋은 웹페이지 즐겨찾기