2010-11-18 5 views
7

HTML 문서에서 텍스트를 선택할 때 DOM 요소 하나에서 다른 요소로 시작할 수 있습니다. 이때 다른 여러 요소를 지나칠 수 있습니다. DOM API를 사용하면 선택된 DOM 요소의 선택 영역, 선택한 텍스트 및 부모 요소까지도 사용할 수 있습니다 (사용 된 브라우저를 기반으로 commonAncestorContainer 또는 parentElement() 사용). 그러나, 내가 선택한 텍스트의 모든 요소를 ​​포함하는 단일 부모 요소를 가져 오는 것 이외의 모든 요소를 ​​나열 할 수있는 방법은 없습니다. 부모를 사용하고 자식 노드를 탐색하면이 부모 내부에서 선택되지 않은 다른 형제가있을 수 있으므로이를 수행하지 않습니다.선택한 텍스트에 대한 모든 DOM 블록 요소 가져 오기

그래서 선택한 텍스트가 포함 된 모든 요소를 ​​가져올 수있는 방법이 있습니까? 나는 주로 블록 요소 (p, h1, h2, h3, ... 등)를 얻는 데 관심이 있지만 모든 요소를 ​​얻을 수있는 방법이 있다면 그 요소를 통해 필터를 통과 할 수 있다고 생각합니다. 필요. 나는 어떤 생각이나 제안이라도 환영한다.

감사합니다.

답변

16

키는 여기 window.getSelection().getRangeAt(0)https://developer.mozilla.org/en/DOM/range

을 당신이 당신이 원하는 것을 할 놀 수있는 몇 가지 샘플 코드입니다. 당신이 정말로이 질문에 대해 원하는 것을 언급하면 ​​사람들이 더 나은 대답을 제공하는 데 도움이 될 것입니다.

var selection = window.getSelection(); 
var range = selection.getRangeAt(0); 
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*"); 

var allSelected = []; 
for (var i=0, el; el = allWithinRangeParent[i]; i++) { 
    // The second parameter says to include the element 
    // even if it's not fully selected 
    if (selection.containsNode(el, true)) { 
    allSelected.push(el); 
    } 
} 


console.log('All selected =', allSelected); 

이 가장 효율적인 방법이 아니다, 당신은로 nextSibling/previousSibling은과 childNodes에와 함께 범위의 startContainer/endContainer를 사용하여 DOM 자신을 통과 할 수있다.

+0

당신이 말한 것처럼 완벽한 해결책은 아니지만 그것을하는 방법에 대한 아이디어를 나에게주었습니다. 그러므로 나는 이것을 나의 필요에 가장 정확한 답으로 선택했다. 정말 고맙습니다. – cria

+0

괜찮은 대답이지만 Internet Explorer <9에서는 작동하지 않습니다. selection.getRangeAt (0);을 호출하기 전에 선택 항목이 존재하는지 확인하는 것도 가능합니다 (선택 항목의 'rangeCount' 속성을 사용하는 것이 가장 쉽습니다). –

+0

내가 언급하지 않은 많은 잡화가있다. 이것은 올바른 방향으로 향하기 시작한 것일 뿐이다. 귀하의 도서관 정말 그것을 처리하는 비 압축 자바 스크립트 22K 필요하고 내가 그것을 필요하면, 난 그냥 사용합니다. –

0

Traversing from the jQuery API처럼 사용할 수 있습니다.

가능할 수 있습니다 .contents()

희망 하시겠습니까?

+0

그래, 거기의 모든 방법이 훌륭합니다. 하지만 브라우저에서 선택한 텍스트 범위를 해당 메서드의 입력으로 사용할 수 있다고 생각하지 않습니까? 또는 어쩌면 내가 뭔가를 놓친 오전 ... 감사합니다 – cria

10

Rangy library을 사용하면이 작업을 수행 할 수 있습니다. 그것은 IE를 포함한 모든 브라우저를위한 DOM Range와 Selection 객체의 구현을 제공하며 추가 Range 메서드를 가지고 있습니다. 이들 중 하나는 getNodes()입니다 :

function isBlockElement(el) { 
    // You may want to add a more complete list of block level element 
    // names on the next line 
    return /h[1-6]|div|p/i.test(el.tagName); 
} 

var sel = rangy.getSelection(); 
if (sel.rangeCount) { 
    var range = sel.getRangeAt(0); 
    var blockElements = range.getNodes([1], isBlockElement); 
    console.log(blockElements); 
} 
+0

나는이 코드가 가장 정확한 하나라는 의심의 여지가 없습니다. 하지만 당신의 lib를 사용하는 것은 lib의 크기가 크기 때문에 내 경우에 과도한 행동입니다. 따라서 내가 처리해야 할 몇 가지 문제가 있더라도 다른 대답을 선택했습니다. 두 가지 대답을 선택할 수있는 선택이 있다면, 나는 물론 당신의 것을 표시 할 것입니다. 훌륭한 lib/work를 유지하십시오. – cria

+0

@cria : 충분히 공정합니다. 당신이 얻는 것은 IE 지원입니다. –

+3

@TimDown Rangy에 감사드립니다. 복잡한 문제를 훨씬 쉽게 만듭니다. –

관련 문제