ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [javascript] Selection과 Range를 통해 내맘대로 커서 조작하기 - Selection편
    IT, 프로그래밍/Javascript 2019. 12. 16. 09:00

     

     

    Selection : 사용자가 마우스를 통해 드래그&클릭하거나 키보드를 통해 선택한 텍스트의 범위를 나타냅니다. 혹은 유저의 현재 커서 위치(caret)를 나타냅니다. 

    크롬, IE 등 브라우저에서는 사용자가 선택한 텍스트에 대한 처리를 지원하기 위해 Selection API를 지원하고 있습니다.

    특히 Selection과 Range 객체는 특히 위지위그(WYSIWYG) 에디터, 텍스트 리치 에디터등을 구현할때 중요하게 사용되니까 필요하신 분들은 꼭 알아두시기 바랍니다.

    Selection은 anchor와 focus를 가지는데요.

    anchor는 텍스트 선택을 시작한 지점, focus는 선택을 끝낸 지점을 말합니다.

    Selection은 방향을 가질 수 있습니다.

    이 말은 텍스트의 왼쪽에서 오른쪽으로, 혹은 오른쪽에서 왼쪽으로 선택할 수 있다는 말인데요.

    이 경우 anchor와 focus는 반대가 될 수 있습니다.

    큐리덕 이라는 문자열을 마우스 드래그로 선택한다고 가정해보면

    왼쪽 -> 오른쪽으로 선택했을 때는 anchor가 0, focus가 2가 되었다면

    오른쪽 -> 왼쪽으로 선택했을때는 anchor가 2, focus가 0이 되는 식입니다.

    Selection 객체는 browsing context를 나타내는 window 객체에서 뽑아올 수 있습니다.


    일반적인 사용법은 window.getSelection()으로 Selection 객체를 호출하며 불러오며, Selection 객체는 Range 객체를 가질 수 있습니다.

    Range 객체는 특정 테두리를 가진 문자열을 말하는데요. 

    Selection을 통해 선택된 텍스트 범위에 대한 정보가 들어있습니다. (노드의 시작 시점, 시작하는 지점에 있는 컨테이너 노드, 공통 부모노드 등등..)

    즉 Selection이 Range를 포함하는 개념이며, Selection안에는 여러개의 Range를 가질 수 있다는 것이죠.

    그러나!

    FireFox의 경우는 한 Selection 안에 여러개의 Range 객체를 가질 수 있지만,

    그 외의 브라우저들은 하나의 Selection 객체안에 단 하나의 Range 객체만을 허용합니다.

    위에서 보듯이 FireFox는 ctrl+마우스 드래그를 통해 여러개의 Range를 선택할 수 있습니다.

     

    위에서 보듯이 Firefox 브라우저의 경우 getRangeAt으로 여러개의 Range 객체에 접근할 수 있음을 볼 수 있습니다.

    ( 파이어폭스 브라우저를 지원할 계획이라면, 크로스 브라우징 처리시에 고려해야할 사항이겠죠? )

     

    Selection 객체를 얻는 방법은 두 가지가 있습니다.

     

    첫째, window object에서 getSelection() 메소드를 통해 불러오는 방법

    둘째, document object에서 getSelection() 메소드를 통해 불러오는 방법인데요.

    두 함수 모두 동일한 Selection 객체를 반환합니다.

     

    Window 객체의 getSelection 메소드의 경우, Window 객체 안의 document 속성에 기반하는 Selection 객체를 반환합니다.

     

    속성


     

    속성명 설명
    anchorNode

    드래그나 키보드 이벤트 등으로 선택이 시작되어진 노드를 반환합니다. 없으면 null을 반환합니다

    anchorOffset

    선택이 시작되어진 노드에서, 시작되어진 텍스트의 시작 지점을 말합니다. 노드의 맨 첫 시작점의 offset은 0입니다. 

    예를들어, "안녕하세요 반갑습니다!" 라는 문장에서, 실제 선택되어진 문장이 "하세요 반갑습니다" 인 경우에, 시작지점은 2이고, 끝 지점은 11 입니다.

    그래서 anchorOffset은 2가 됩니다.

    focusNode 선택이 끝난 지점에 있는 노드를 반환합니다. 없으면 null을 반환합니다.
    focusOffset 선택이 끝난 노드에서, 텍스트의 종료 지점을 말합니다. 노드의 맨 첫 시작점의 offset은 0입니다.
    isCollapsed anchor와 focus가 같은 지점에 있는지 여부를 반환합니다. 클릭하면 anchor와 focus가 같은 지점에 존재합니다. 입력이 가능하면 커서가 깜박이고 있을겁니다.
    rangeCount 현재 브라우저 컨텍스트에 존재하는 존재하는 Range의 개수를 반환합니다.
    type

    collapsed이면 "Caret", 범위가 선택된 상태면 "Range", 아무것도 선택되어진 상태가 아니라면 ( 아무 이벤트도 발생되지 않은경우라면 ) "None"을 반환합니다.

     

    메소드


    메소드명 파라미터 파라미터 설명 설명
    getRangeAt index 꺼내올 Range 객체의 인덱스 번호입니다. 특정 index에 있는 Range 객체를 꺼내옵니다.
    addRange range 추가할 Range 객체 현재 Selection에 Range를 추가합니다.
    collapse node

    접을 노드

    (Selection 안에 존재하는 노드이어야함)

    넘겨진 노드와 offset으로 Range를 접습니다.
    offset optional, 이동시킬 노드가 자식 노드를 가지고 있을 경우에, 몇 번째 자식노드에서 접을것인지 지정할 수 있습니다.기본값의 경우 0으로 설정되어 있습니다.
    collapseToEnd     선택되어진 range의 끝 지점으로 접습니다.
    collapseToStart     선택되어진 range의 시작 지점으로 접습니다.
    containsNode node 포함되어 있는지 확인할 노드 주어진 노드가 선택된 범위 안에 존재하는지 확인하여 boolean 값으로 반환합니다.
    partialContainment

    optional,

    기본값은 false입니다.

    노드의 시작과 끝이 선택된 범위와 동일할때 반환될 방식을 지정

    true: 노드와 선택된 범위가 동일할때 포함된 것으로 침

    false: 노드와 선택된 범위가 동일할때 포함되지 않은것으로 침

    deleteFromDocument     선택된 범위를 Document 객체에서 제거합니다. ( 선택된 범위를 아예 문서에서 없애버리는 메소드 )
    removeAllRanges     Selection 객체 안에 있는 모든 Range를 제거하여, 아무것도 선택되지 않은 상태로 만듭니다.
    removeRange range 제거할 Range 객체

    특정 range를 Selection 객체 안에서 제거합니다.

    제거할 Range 객체는 Selection 객체 안에 포함되어 있어야 합니다.

    extend node focus로 지정할 노드 anchor는 가만히 두고 focus만 주어진 노드와 offset으로 이동시킵니다.
    offset

    optional, 이동시킬 노드가 자식 노드를 가지고 있을 경우에, 몇 번째 자식노드로 focus를 이동시킬것인지 지정할 수 있습니다.기본값의 경우 0으로 설정되어 있습니다.

    setBaseAndExtent



    anchorNode anchor로 지정할 노드

    주어진 노드들로 선택 범위의 시작과 끝 지점을 지정합니다.

    extend가 선택의 끝만 지정했다면, setBaseAndExtent는 시작 노드와 끝 노드를 지정할 수 있습니다.

    anchorOffset 이동시킬 노드가 자식 노드를 가지고 있을 경우에, 몇 번째 자식노드로 anchor를 이동시킬것인지 지정할 수 있습니다.기본값의 경우 0으로 설정되어 있습니다.
    focusNode focus로 지정할 노드
    focusOffset 이동시킬 노드가 자식 노드를 가지고 있을 경우에, 몇 번째 자식노드로 focus를 이동시킬것인지 지정할 수 있습니다.기본값의 경우 0으로 설정되어 있습니다.
    selectAllChildren parentNode 자식들을 선택할 부모노드 부모 노드를 넘겨주면, 부모노드 아래에 있는 모든 자식 노드가 선택되어 집니다.
    setPosition     collapse() 메소드와 동일함
    empty     removeAllRange() 메소드와 동일함

     

    이벤트


    이벤트명 설명
    selectstart 유저의 드래그나 클릭 등의 행위에 의해 새로운 Range 객체가 연결될 때, 발생되는 이벤트 
    selectionchange 현재 붙어있는 Range 객체가 떨어지고 새로운 Range 객체가 붙거나, 현재 Range 객체의 경계선이 변형될때 발생하는 이벤트. 

     

     

    아래의 예제를 보면서 API의 동작을 확인해 보시기 바랍니다.

    브라우저의 개발자 도구를 켜고 확인하셔야 합니다.

     

    See the Pen oNgzdOB by giduck (@giduck) on CodePen.

Designed by Tistory.