콘텐츠 편집 가능한 HTML 요소에서 프로그래밍 방식으로 텍스트를 선택 하시겠습니까?


119

JavaScript에서는 input또는 textarea요소의 텍스트를 프로그래밍 방식으로 선택할 수 있습니다 . 로 입력에 초점을 맞춘 ipt.focus()다음로 해당 내용을 선택할 수 있습니다 ipt.select(). 을 사용하여 특정 범위를 선택할 수도 있습니다 ipt.setSelectionRange(from,to).

내 질문은 : contenteditable요소에서도 이것을 수행하는 방법이 있습니까?

elem.focus()캐럿을 contenteditable요소 에 넣을 수 있지만 나중에 실행하면 작동 elem.select()하지 않는다는 것을 알았 습니다 setSelectionRange. 웹에서 아무것도 찾을 수 없지만 잘못된 것을 찾고있는 것 같습니다 ...

그건 그렇고, 차이가 있다면 Chrome 확장 프로그램이기 때문에 Google Chrome에서 작동하기 위해 필요합니다.

답변:


170

Chrome에서 요소의 모든 콘텐츠 (contenteditable 여부)를 선택하려는 경우 방법은 다음과 같습니다. Firefox, Safari 3+, Opera 9+ (아마도 이전 버전도 가능) 및 IE 9에서도 작동합니다. 문자 수준까지 선택 항목을 만들 수도 있습니다. 필요한 API는 DOM 범위 (현재 사양은 DOM 레벨 2 , MDN 참조 ) 및 선택이며 새 범위 사양 ( MDN 문서 )의 일부로 지정됩니다 .

function selectElementContents(el) {
    var range = document.createRange();
    range.selectNodeContents(el);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

var el = document.getElementById("foo");
selectElementContents(el);

15
여분의 호환성 (을) 위해 당신은 호출해야합니다 selectElementContents()A의 setTimeout()또는 requestAnimationFrame()경우는 호출 onfocus. jsfiddle.net/rudiedirkx/MgASG/1/show
Rudie

@Dylan : 잘 모르겠습니다 : 질문에 OP가 이미 focus().
Tim Down

4
어떤 응용 프로그램에 대한 @Rudie 호환성 ?
yckart

데스크톱에서 잘 작동합니다. 모바일 브라우저에서는 작동하지 않습니다. 선택하지 않았습니다. iPhone iOS 11에서 Safari 및 Chrome을
campbell

1
@campbell : 이미 선택 항목이있는 경우 최소한 iOS의 Safari에서 작동합니다 . 그렇지 않으면 브라우저는 아마도 사용자 경험상의 이유로 JavaScript가 선택 항목을 표시하는 것을 허용하지 않습니다.
Tim Down

34

Tim Downs 답변 외에도 oldIE에서도 작동하는 솔루션을 만들었습니다.

var selectText = function() {
  var range, selection;
  if (document.body.createTextRange) {
    range = document.body.createTextRange();
    range.moveToElementText(this);
    range.select();
  } else if (window.getSelection) {
    selection = window.getSelection();
    range = document.createRange();
    range.selectNodeContents(this);
    selection.removeAllRanges();
    selection.addRange(range);
  }
};

document.getElementById('foo').ondblclick = selectText;​

IE 8+, Firefox 3+, Opera 9+ 및 Chrome 2+에서 테스트되었습니다. 심지어 나는 그것을 jQuery 플러그인으로 설정했습니다.

jQuery.fn.selectText = function() {
  var range, selection;
  return this.each(function() {
    if (document.body.createTextRange) {
      range = document.body.createTextRange();
      range.moveToElementText(this);
      range.select();
    } else if (window.getSelection) {
      selection = window.getSelection();
      range = document.createRange();
      range.selectNodeContents(this);
      selection.removeAllRanges();
      selection.addRange(range);
    }
  });
};

$('#foo').on('dblclick', function() {
  $(this).selectText();
});

... 그리고 누가 관심을 갖고 있는지, 여기 모든 커피 중독자들에게 똑같은 내용이 있습니다.

jQuery.fn.selectText = ->
  @each ->
    if document.body.createTextRange
      range = document.body.createTextRange()
      range.moveToElementText @
      range.select()
    else if window.getSelection
      selection = window.getSelection()
      range = document.createRange()
      range.selectNodeContents @
      selection.removeAllRanges()
      selection.addRange range
    return

최신 정보:

전체 페이지 또는 편집 가능 영역의 내용 (으로 contentEditable표시됨) 을 선택하려면 로 전환 designMode하고 사용하여 훨씬 간단하게 수행 할 수 있습니다.document.execCommand .

좋은있다 MDN에서 시작 지점littledocumentation은 .

var selectText = function () {
  document.execCommand('selectAll', false, null);
};

(IE6 +, Opera 9+, Firefoy 3+, Chrome 2+에서 잘 작동합니다) http://caniuse.com/#search=execCommand


10

기존 답변은 모두 div요소를 다루기 때문에 spans 로 수행하는 방법을 설명하겠습니다 .

에서 텍스트 범위를 선택할 때 미묘한 차이가 span있습니다. 텍스트 시작 및 끝 인덱스를 전달할 수 있으려면 여기에Text 설명 된대로 노드 를 사용해야합니다 .

startNode가 Text, Comment 또는 CDATASection 유형의 노드 인 경우 startOffset은 startNode 시작부터의 문자 수입니다. 다른 노드 유형의 경우 startOffset은 startNode 시작 사이의 자식 노드 수입니다.

var e = document.getElementById("id of the span element you want to select text in");
var textNode = e.childNodes[0]; //text node is the first child node of a span

var r = document.createRange();
var startIndex = 0;
var endIndex = textNode.textContent.length;
r.setStart(textNode, startIndex);
r.setEnd(textNode, endIndex);

var s = window.getSelection();
s.removeAllRanges();
s.addRange(r);

정말이어야합니다 : r.setStart(e.firstChild,0); r.setEnd(e.lastChild,e.lastChild.textContent.length); 물론 e.firstChild가 실제로 null이 아닌지 확인해야합니다.
Yorick

2
a <div><span>요소 에서 선택하는 것에는 차이가 없습니다 . 적어도 당신이 설명하는대로는 아닙니다.
Tim Down

div와 span에는 차이가 있으며, 경우에 따라 div에 대한 솔루션이 span에서 제대로 작동하지 않습니다. 예를 들어 div 솔루션을 사용하여 프로그래밍 방식으로 텍스트를 선택한 다음 새 콘텐츠를 붙여 넣으면 전체 텍스트가 아닌 일부만 대체되며 chrome과 firefox간에 차이가 있습니다
neosonne

6

Rangy를 사용하면 동일한 코드로이 크로스 브라우저를 수행 할 수 있습니다. Rangy는 선택을위한 DOM 메소드의 브라우저 간 구현입니다. 그것은 잘 테스트되었으며 이것을 훨씬 덜 고통스럽게 만듭니다. 나는 그것 없이는 contenteditable을 만지지 않는다.

여기에서 rangy를 찾을 수 있습니다.

http://code.google.com/p/rangy/

프로젝트가 엉망인 경우 브라우저가 IE 8 이하이고 선택 항목에 대해 완전히 다른 기본 API가 있더라도 항상 이것을 작성할 수 있습니다.

var range = rangy.createRange();
range.selectNodeContents(contentEditableNode);
var sel = rangy.getSelection();
sel.removeAllRanges();
sel.addRange(range);

여기서 "contentEditableNode"는 contenteditable 속성이있는 DOM 노드입니다. 다음과 같이 가져올 수 있습니다.

var contentEditable = document.getElementById('my-editable-thing');

또는 jQuery가 이미 프로젝트의 일부이고 편리하다고 생각하는 경우 :

var contentEditable = $('.some-selector')[0];


4

일을하는 현대적인 방법은 이와 같습니다. MDN 에 대한 자세한 내용

document.addEventListener('dblclick', (event) => {
  window.getSelection().selectAllChildren(event.target)
})
<div contenteditable="true">Some text</div>


감사합니다. 잘 작동합니다! Fwiw, 그 MDN 페이지는이 기술을 실험적인 것으로 표시합니다. 하지만 2020 년 6 월 현재 Chrome 및 FF 버전에서 작동합니다.
JohnK

2

[실수 수정 업데이트]

다음은 Chrome에서 잘 작동하는 것으로 보이는이 답변에서 수정 된 예입니다 . contenteditable div에서 범위 선택

var elm = document.getElementById("myText"),
    fc = elm.firstChild,
    ec = elm.lastChild,
    range = document.createRange(),
    sel;
elm.focus();
range.setStart(fc,1);
range.setEnd(ec,3);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

HTML은 다음과 같습니다.

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