본문 바로가기
웹개발/js

Selection 과 Range 사용자가 드래그 등으로 선택한 텍스트 및 위치

by heavenLake 2021. 8. 11.
반응형

 

 

 

 

 

 

 출처 : https://ohgyun.com/547

 

참고:

https://developer.mozilla.org/en-US/docs/Web/API/Selection

https://developer.mozilla.org/en-US/docs/Web/API/Range

https://javascript.info/selection-range#

 

 

 

Selection

 

Selection 은 window.getSelection() 이나 다른 메서드의 호출로 생성되는 객체이다.

사용자가 드래그 등으로 여러 엘리먼트에 걸쳐 선택한 텍스트를 대표한다.

window또는 document를 이용해서 갖어 올수 있다.


  function getSelection() {
      return (window.getSelection) ? window.getSelection() : document.selection;
  }

 

selection 객체는 사용자가 선택한 `range`로 표현된다.

보통 한 개의 range 만 갖고 있고, 아래 코드처럼 가져올 수 있다.

 

var selObj = window.getSelection();

var range  = selObj.getRangeAt(0);

 

selObj: Selection 객체

range: Range 객체

 

 

선택된 값은 selection 객체의 toString()을 호출해서 가져올 수 있다.

 

selObj.toString(); //—> 현재 선택한 텍스트

 

 

 

Selection 에 사용되는 용어 정리

 

anchor

  셀렉션의 시작점.

  마우스로 드래그해서 선택했다면, anchor 는 최초에 마우스가 클릭된 지점이다.

  사용자가 마우스나 키보드로 셀렉션을 수정해도, anchor 는 변경되지 않는다.

  텍스트를 위/아래로 드래그했을 때 고정된 지점이 anchor 이다.

 

focus

  셀렉션의 끝점.

  마우스로 셀렉션을 만들었다면, 마우스를 뗀 곳이 셀렉션의 focus 지점이다.

  사용자가 마우스나 키보드로 셀렉션을 수정할 때마다 변경된다.

 

range

  문서에 인접한 부분.

  텍스트 노드를 포함한 전체 노드를 포함할 수 있다.

  일반적으로 사용자는 한 개의 레인지만 선택할 수 있지만, 컨트롤 키 등으로 멀티 레인지를 선택할 수도 있다.

  레인지는 range 객체로 리턴되며, 스크립트에 의해 추가되거나 삭제될 수 있다.

 

 

 

Selection의 주요 속성

 

Selection.anchorNode

  시작 노드

 

Selection.anchorOffset

  시작 노드에서 anchor 의 오프셋.

  anchorNode 가 텍스트 노드이면 anchor 이전의 문자열의 개수이고,

  anchorNode 가 엘리먼트일 경우엔 anchor 보다 앞에 있는 자식 노드의 개수를 의미한다.

 

Selection.focusNode

  끝 노드

 

Selection.focusOffset

  끝 노드에서 focus 의 오프셋.

  focusNode 가 텍스트 노드이면 focus 이전의 문자열의 개수이고,

  focusNode 가 엘리먼트일 경우엔 focus 보다 앞에 있는 자식 노드의 개수를 의미한다.

 

Selection.isCollapsed

  셀렉션의 시작지점과 끝지점이 동일한지의 여부

 

Selection.rangeCount

  셀렉션 내의 레인지 개수

 

 

 

 

 

 

Range

 

Range 인터페이스는 노드와 텍스트 노드를 포함한 문서의 일부(fragment)이다.

'문서의 특정 부분’을 정의하는 것이라 생각하면 쉽다.

 

레인지를 생성할 수 있는 방법은 아래와 같다.

- document.createRange()

- Selection 객체의 getRangeAt() 메서드

- Range() 생성자

 

 

Range의 주요 속성

 

Range.collapsed

  레인지의 시작점과 끝점이 동일한지 여부

 

Range.commonAncestorContainer

  시작 컨테이너와 끝 컨테이너를 포함하고 있는 상위 노드

 

Range.endContainer

  레인지가 끝나는 지점의 끝 컨테이너 노드

 

Range.endOffset

  endContainer 노드에서 끝 지점의 오프셋

 

Range.startContainer

  레인지가 시작하는 지점의 컨테이너 노드

 

Range.startOffset

  startContainer 노드에서 시작 지점의 오프셋

 

 

출처 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=parkjy76&logNo=30036746084

 

///////    커서가 위치한 곳에 태그 넣기   ///////

에디터 기능이 지원되지 않는 오래된 시스템에 간단한 에디터 기능을 추가할 일이 생겼다.
IE는 document.selection으로 오브젝트 지정후 createRange, createTextRange등을 이용하면
되지만 FF의 경우 document.getSelection()을 사용할경우 일반적인 document상의 선택 문자열을
체크 가능하지만 textarea에 선택한 문자열이 체크가 되지 않았다.
결국 selectionStart와 selectionEnd로 핸들링하였다.

아래의 소스는 IE와 FF대응되는 textarea베이스의 소스이다.
textarea에 글을 입력하고 그후 색깔을 지정하고 싶은 문자열을 지정
버튼을 누르면 팝업창이 뜨고 팝업창에서 색깔을 선택(클릭)하면 <font>문자열</font>형식으로 textarea에 입려되는 소스이다.
색깔선택등은 생략함.
기본적으로 desc.html(텍스트 입력페이지), popup.html(팝업페이지)로 구성했다.

--------------- desc.html --------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script language="javascript">
function poppop()
{
    poppop = window.open('popup.html','','height=100,width=100');   
}
</script>
</head>
<body>
<textarea id="comment" name="comment" cols="50" rows="20" wrap="virtual" style="width:550px; font-size:12px;">Good job!!</textarea>
<a href=# onClick="poppop();">Popup</a>
</body>
</html>

--------------- popup.html --------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script language="javascript">
function insert_tag(sTag, eTag)
{
    var objSelection = opener.document.selection;
    var objTextArea = opener.document.getElementById('comment');
    //var objTextArea = opener.document.getElementsByName('comment')[0];
    //var objTextArea = opener.document.forms['descFrm'].elements['comment'];
    objTextArea.focus();
   
    if(typeof objSelection != 'undefined') //IE
    {
        var sRange = objSelection.createRange();
        var selectedText = sRange.text;

        sRange.text = sTag + selectedText + eTag;
        /*
        sRange = objSelection.createRange();

        if (selectedText.length == 0) sRange.move('character', -eTag.length);
        else sRange.moveStart('character', sTag.length + selectedText.length + eTag.length);
        sRange.select();
        */
    }
    else if(typeof objTextArea.selectionStart != 'undefined') //FF
    {
        var sStart = objTextArea.selectionStart;
        var sEnd = objTextArea.selectionEnd;
        var selectedText = objTextArea.value.substring(sStart, sEnd);
        //var selectedText = objTextArea.value.substring(sStart, sEnd-sStart);
        objTextArea.value = objTextArea.value.substr(0, sStart) + sTag + selectedText + eTag + objTextArea.value.substr(sEnd);
        /*
        var pos;
        if (selectedText.length == 0) pos = sStart + sTag.length;
        else pos = sStart + sTag.length + selectedText.length + eTag.length;
       
        objTextArea.selectionStart = pos;
        objTextArea.selectionEnd = pos;
        */
    }
    else
    {
        objTextArea.value += sTag + eTag;
        /*
        var pos;
        var regexp = new RegExp('^[0-9]{0,3}$');
       
        while(!regexp.test(pos))
        {
            pos = prompt("position (0.." + objTextArea.value.length + "):", "0");
        }
       
        if(pos > objTextArea.value.length) pos = objTextArea.value.length;
       
        objTextArea.value = objTextArea.value.substr(0, pos) + sTag + 'kkk' + eTag + objTextArea.value.substr(pos);
        */
    }

    //self.close();
}
</script>
</head>
<body>
<div align="center"><input type="button" onClick="insert_tag('<font color=#FFFFFF>', '</font>');" /></div>
</body>
</html>

반응형

댓글