Range API: 텍스트 범위 정의와 이해
Range는 문서 내에서 선택된 부분을 나타내는 객체로, 두 개의 경계(시작점(startContainer,StartOffset)과 끝점(endContainer, endOffset))를 정의합니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Range 기본 사용</title>
</head>
<body>
<div id="textBlock">
안녕하세요, <em>여러분!</em> 환영합니다.
</div>
<script>
const textBlock = document.getElementById('textBlock');
const range = new Range();
// "여러분! 환영" 선택: <em>부터 텍스트 노드 끝까지
range.setStart(textBlock.childNodes[1], 0); // <em>의 첫 문자
range.setEnd(textBlock.childNodes[2], 7); // " 환영합니다"의 끝까지
console.log('선택 범위:', range.toString()); // "여러분! 환영"
</script>
</body>
</html>
- setStart/setEnd: 특정 콘텐츠를 추출할 수 있는 범위 지정
- toString(): 선택된 텍스트 반환
Range 조작: 선택 영역 변경
Range API는 선택된 콘텐츠를 조작하는 다양한 메서드를 제공합니다. 선택 영역을 삭제, 삽입, 감싸는 등의 작업을 지원합니다.
주요 메서드
- deleteContents(): 범위 내용 삭제
- extractContents(): 선택 영역 잘라내기
- insertNode(): 노드 삽입
- surroundContents(): 범위를 새 요소로 감쌈
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Range로 하이라이트</title>
<style>
mark { background: #fff176; padding: 2px; }
</style>
</head>
<body>
<p id="article">오늘은 좋은 날씨가 이어지고 있습니다.</p>
<button id="markBtn">하이라이트</button>
<script>
const article = document.getElementById('article');
const markBtn = document.getElementById('markBtn');
markBtn.addEventListener('click', () => {
const range = new Range();
range.setStart(article.childNodes[0], 4); // "좋은"부터
range.setEnd(article.childNodes[0], 9); // " 날씨"까지
try {
const mark = document.createElement('mark');
range.surroundContents(mark);
console.log('하이라이트 적용:', range.toString());
} catch (e) {
console.error('하이라이트 실패:', e.message);
}
});
</script>
</body>
</html>
- surroundContents: 메서드는 선택 영역이 완전한 노드 경계를 포함할 때만 동작합니다. 만약 일부만 포함되거나 중첩된 태그가 불완전하면 에러가 발생할 수 있으므로, 상황에 맞게 Range를 조정해야 합니다.
불완전 태그로 에러 발생
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Range로 하이라이트</title>
<style>
mark { background: #fff176; padding: 2px; }
</style>
</head>
<body>
<p id="article">오늘은 <span>좋은</span> 날씨가 이어지고 있습니다.</p>
<button id="markBtn">하이라이트</button>
<script>
const article = document.getElementById('article');
const markBtn = document.getElementById('markBtn');
markBtn.addEventListener('click', () => {
const range = new Range();
range.setStart(article.childNodes[1], 0); // <span> 시작
range.setEnd(article.childNodes[2], 4); // " 날씨"까지
try {
const mark = document.createElement('mark');
const fragment = range.extractContents();
mark.appendChild(fragment);
range.insertNode(mark);
//range.surroundContents(mark);
console.log('하이라이트 적용:', range.toString());
} catch (e) {
console.error('하이라이트 실패:', e.message);
}
});
</script>
</body>
</html>
Selection API – 현재 선택된 영역 가져오기
Selection 객체는 사용자가 현재 문서에서 선택한 영역을 나타냅니다. window.getSelection() 또는 document.getSelection()을 사용하면 Selection 객체를 얻을 수 있으며, 이 객체에는 최소한 하나의 Range가 포함됩니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Selection 복사</title>
<style>
#content { padding: 10px; border: 1px solid #ddd; }
#copyBtn { margin-top: 10px; }
</style>
</head>
<body>
<div id="content">여기에서 텍스트를 선택하고 버튼을 눌러 복사하세요.</div>
<button id="copyBtn">선택 복사</button>
<script>
const copyBtn = document.getElementById('copyBtn');
copyBtn.addEventListener('click', () => {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const selectedText = selection.toString();
if (selectedText) {
navigator.clipboard.writeText(selectedText)
.then(() => alert('복사 완료: ' + selectedText))
.catch(err => console.error('복사 실패:', err));
} else {
alert('선택된 텍스트가 없습니다.');
}
}
});
</script>
</body>
</html>
폼 컨트롤에서의 텍스트 선택
<input>과 <textarea>에서는 selectionStart, selectionEnd, setRangeText()로 선택 영역을 직접 제어할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 텍스트 조작</title>
<style>
textarea { width: 300px; height: 80px; padding: 5px; }
button { margin-top: 5px; }
</style>
</head>
<body>
<textarea id="editor">안녕하세요, 텍스트를 선택해 보세요.</textarea>
<button id="replaceBtn">선택 대체</button>
<script>
const editor = document.getElementById('editor');
const replaceBtn = document.getElementById('replaceBtn');
replaceBtn.addEventListener('click', () => {
const start = editor.selectionStart;
const end = editor.selectionEnd;
if (start !== end) {
editor.setRangeText('[대체됨]', start, end, 'select');
console.log('대체된 범위:', start, end);
} else {
alert('텍스트를 먼저 선택하세요.');
}
});
</script>
</body>
</html>
'브라우저' 카테고리의 다른 글
이벤트 루프와 태스트 분리와 웹 워커를 이용한 병렬 처리 (0) | 2025.02.21 |
---|---|
MutationObserver로 DOM 변화 실시간 제어하기 (0) | 2025.02.21 |
외부 리소스 로딩 감지:onload와 onerror 이벤트 (0) | 2025.02.21 |
defer와 async로 최적화된 스크립트 로딩 (0) | 2025.02.21 |
HTML 문서 생명주기 (0) | 2025.02.21 |