텍스트 영역에서 캐럿 열 (픽셀이 아닌) 위치를 문자로 시작하는 방법은 무엇입니까?


174

<textarea>JavaScript를 사용하여 캐럿 위치를 어떻게 얻 습니까?

예를 들면 다음과 같습니다. This is| a text

이 반환되어야합니다 7.

커서 / 선택 영역을 둘러싼 문자열을 어떻게 반환합니까?

예 : 'This is', '', ' a text'.

"is"라는 단어가 강조 표시되면을 반환 'This ', 'is', ' a text'합니다.


이 질문을 참조 stackoverflow.com/questions/164147/...을 : 당신이 그 여기에 대한 또한 메모 줄 바꿈을 할 경우 stackoverflow.com/questions/235411/...
bobince

1
jQuery를 사용하는 경우 jquery caret plugin $ ( 'textarea'). getSelection (). start plugins.jquery.com/plugin-tags/caret @ ++
redochka

blog.vishalon.net/index.php/ 에서 좋은 솔루션을 찾았습니다 … 파이어 폭스와 크롬에서 테스트했으며 두 가지 모두에서 작동했습니다. 필자는 IE + Opera에서도 작동한다고 말합니다.
pycoder112358

간단한 사용 textarea.selectionStart, textarea. selectionEnd, textarea.setSelectionRange developer.mozilla.org/en-US/docs/Web/API/HTMLTextAreaElement
EAndreyF

답변:


173

Firefox, Safari 및 기타 Gecko 기반 브라우저를 사용하면 textarea.selectionStart를 쉽게 사용할 수 있지만 작동하지 않는 IE의 경우 다음과 같은 작업을 수행해야합니다.

function getCaret(node) {
  if (node.selectionStart) {
    return node.selectionStart;
  } else if (!document.selection) {
    return 0;
  }

  var c = "\001",
      sel = document.selection.createRange(),
      dul = sel.duplicate(),
      len = 0;

  dul.moveToElementText(node);
  sel.text = c;
  len = dul.text.indexOf(c);
  sel.moveStart('character',-1);
  sel.text = "";
  return len;
}

( 여기에서 완전한 코드 )

또한 jQuery FieldSelection 플러그인 을 확인하는 것이 좋습니다 .

편집 : 실제로 위 코드를 다시 구현했습니다.

function getCaret(el) { 
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
        rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    return rc.text.length; 
  }  
  return 0; 
}

예를 확인 하십시오 .


1
캐럿이 빈 줄에있을 때 캐럿 위치를 구분하지 않습니다. 참조 stackoverflow.com/questions/3053542/...
팀 다운

4
이 답변은 빈 줄 문제를 다루지 않습니다.
Tim Down

6
CONTENTEDITABLE div에 어떻게 이것을 사용할 수 있습니까?
Muhammet Göktürk Ayan

1
이 대답을 약간 바꿔 말하면 Safari (and other Gecko based browsers)Safari가 Gecko를 사용한다는 것을 암시하는 것 같습니다. Gecko는 Mozilla의 엔진입니다. Safari는 WebKit을 사용합니다.
쓸모없는 코드

1
위치 0의 캐럿은 테스트에 실패합니다 if (el.selectionStart) { return el.selectionStart; }...
okm

57

2010 년 9 월 5 일 업데이트

모든 사람 이이 문제에 대해 여기에서 지시하는 것처럼 보니 비슷한 질문에 대한 답변을 추가합니다.이 답변과 동일한 코드가 포함되어 있지만 관심있는 사람들을위한 배경 지식이 있습니다.

IE의 document.selection.createRange에는 선행 또는 후행 빈 줄이 포함되지 않습니다

IE에서 후행 줄 바꿈을 설명하는 것은 까다 롭고이 질문에 대한 다른 답변을 포함하여 올바르게 수행하는 솔루션을 보지 못했습니다. 그러나 다음 함수를 사용하면 a <textarea>또는 text 내에서 선택 항목의 시작과 끝 (캐럿의 경우와 동일)을 반환 할 수 있습니다 <input>.

IE에서이 기능이 제대로 작동하려면 텍스트 영역에 포커스가 있어야합니다. 확실하지 않은 경우 focus()먼저 텍스트 영역의 메서드를 호출하십시오 .

function getInputSelection(el) {
    var start = 0, end = 0, normalizedValue, range,
        textInputRange, len, endRange;

    if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
        start = el.selectionStart;
        end = el.selectionEnd;
    } else {
        range = document.selection.createRange();

        if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = end = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;

                if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                    end = len;
                } else {
                    end = -textInputRange.moveEnd("character", -len);
                    end += normalizedValue.slice(0, end).split("\n").length - 1;
                }
            }
        }
    }

    return {
        start: start,
        end: end
    };
}

실례지만 ' range && range.parentElement () '는 무엇을 의미합니까?
sergzach

IE에서 캐럿의 위치를 ​​얻으려면 문제가 있습니다 (선택이 비어있는 경우). 이 경우 시작으로 0 을 , 끝으로 문자열 길이 를 리턴합니다 ( 범위 && range.parentElement () == el 대신 true 를 사용하는 경우 ).
sergzach

@ sergzach : range && range.parentElement() == el선택이 텍스트 영역 내에 있고 필요한지 테스트 할 수 있습니다. 텍스트 영역에 초점이있는 한 캐럿 위치를 얻는 기능에는 문제가 없습니다 . 확실하지 않으면를 focus()호출하기 전에 텍스트 영역의 메서드를 호출하십시오 getInputSelection(). 답변에 메모를 추가하겠습니다.
Tim Down

1
@Tim : 선택을 나타 내기 위해 div 요소를 클릭 할 때 "시작"과 "끝"은 항상 동일합니다.
Misha Moroshko

3
@Misha : 그것은 함수의 결함이 아닙니다. 그것이 함수가 실행될 때 실제로 선택되는 것입니다. 경고 상자를 닫은 후 시각적으로 볼 수 있습니다. 최근 질문에 대한 답변에서 언급했듯이 가능한 두 가지 해결 방법은 mousedown이벤트를 사용하거나 요소에 추가 unselectable="on"하는 것 <div>입니다.
Tim Down

3

IE의 캐리지 리턴을 설명하기 위해 위 함수를 수정했습니다. 테스트되지 않았지만 코드에서 이와 비슷한 작업을 수행 했으므로 실행 가능해야합니다.

function getCaret(el) {
  if (el.selectionStart) { 
    return el.selectionStart; 
  } else if (document.selection) { 
    el.focus(); 

    var r = document.selection.createRange(); 
    if (r == null) { 
      return 0; 
    } 

    var re = el.createTextRange(), 
    rc = re.duplicate(); 
    re.moveToBookmark(r.getBookmark()); 
    rc.setEndPoint('EndToStart', re); 

    var add_newlines = 0;
    for (var i=0; i<rc.text.length; i++) {
      if (rc.text.substr(i, 2) == '\r\n') {
        add_newlines += 2;
        i++;
      }
    }

    //return rc.text.length + add_newlines;

    //We need to substract the no. of lines
    return rc.text.length - add_newlines; 
  }  
  return 0; 
}

2

IE를 지원하지 않아도되는 경우 selectionStart및의 selectionEnd속성을 사용할 수 있습니다 textarea.

캐럿 위치를 얻으려면 다음을 사용하십시오 selectionStart.

function getCaretPosition(textarea) {
  return textarea.selectionStart
}

선택을 둘러싼 문자열을 얻으려면 다음 코드를 사용하십시오.

function getSurroundingSelection(textarea) {
  return [textarea.value.substring(0, textarea.selectionStart)
         ,textarea.value.substring(textarea.selectionStart, textarea.selectionEnd)
         ,textarea.value.substring(textarea.selectionEnd, textarea.value.length)]
}

JSFiddle 데모 .

HTMLTextAreaElement docs 도 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.