2010-03-28 10 views
6

현재 프로젝트에는 제공된 선택자를 기반으로 요소 및 해당 하위 항목의 텍스트 컨텐츠를 수집하는 작업이 포함됩니다.JavaScript : 요소를 무시하고 스크립트를 무시하고 텍스트를 가져 오는 방법은 무엇입니까?

<div id="content"> 
    <p>This is some text.</p> 
    <script type="text/javascript"> 
    var test = true; 
    </script> 
    <p>This is some more text.</p> 
</div> 

내 스크립트 (약간의 공백 정리 후) 반환 :

이 텍스트 인 선택 #content 공급이 HTML에 대해 실행

예를 들어

. var test = true; 이것은 더 많은 텍스트입니다.

그러나 <script> 요소 내에있는 텍스트 노드는 무시해야합니다.

내 현재 코드 (기술적으로,이 하나 이상 제공하는 선택기를 기반으로 일치)의 발췌 한 것입니다 :

// get text content of all matching elements 
for (x = 0; x < selectors.length; x++) { // 'selectors' is an array of CSS selectors from which to gather text content 
    matches = Sizzle(selectors[x], document); 
    for (y = 0; y < matches.length; y++) { 
    match = matches[y]; 
    if (match.innerText) { // IE 
     content += match.innerText + ' '; 
    } else if (match.textContent) { // other browsers 
     content += match.textContent + ' '; 
    } 
    } 
} 

그것은 (단지 요소 내의 모든 텍스트 노드를 반환에서 조금 지나치게 단순한입니다 및 그 자손)을 제공합니다. 내가 찾고있는 솔루션은 <script> 요소에 해당하는 것을 제외하고 모든 텍스트 노드를 반환합니다. 특히 고성능 일 필요는 없지만 궁극적으로 브라우저 간 호환이 필요합니다.

셀렉터와 일치하는 요소의 모든 자식을 반복적으로 처리하고 <script> 요소 내에있는 노드 이외의 모든 텍스트 노드를 누적해야한다고 가정합니다. 이미 모든 텍스트 노드에서 누적 된 문자열에 롤인 된 JavaScript를 식별 할 수있는 방법이없는 것처럼 보입니다.

jQuery의 선택기 논리를 사용할 수 있도록 Sizzle 선택기 엔진을 사용하고 있음을 알았지 만 성능/대역폭상의 이유로 jQuery를 사용할 수 없습니다.

미리 도움을 청하십시오!

답변

8
function getTextContentExceptScript(element) { 
    var text= []; 
    for (var i= 0, n= element.childNodes.length; i<n; i++) { 
     var child= element.childNodes[i]; 
     if (child.nodeType===1 && child.tagName.toLowerCase()!=='script') 
      text.push(getTextContentExceptScript(child)); 
     else if (child.nodeType===3) 
      text.push(child.data); 
    } 
    return text.join(''); 
} 

은 또는, 더 빨리 :

var scripts= element.getElementsByTagName('script'); 
while (scripts.length!==0) 
    scripts[0].parentNode.removeChild(scripts[0]); 
return 'textContent' in element? element.textContent : element.innerText; 
+0

굉장합니다, 고마워요. 나는 첫 번째 접근법을 사용했다. 아마 '

2

편집는 :

그럼 먼저 나에게 그 쓸쓸한에 지글 지글와 메신저 너무 익숙하지 가정 해 봅시다

, jsut는 ... 그 말 사용 라이브러리 내 ..

나는이 작업을 수행해야한다면 나는 다음과 같이 할 것이다 :

나는 그것을 테스트하지는 못했다. 그러나 그것은 당신에게 아이디어를 줄 것이다.


캔트 :-) 더 방향과 희망이 다른 사람의 의지 파이프까지 그냥 같은 ... 부모 노드를 잡아 루프에 nodeName을 확인 : JQuery와 당연히

if(match.parentNode.nodeName.toLowerCase() != 'script' && match.nodeName.toLowerCase() != 'script') { 
    match = matches[y]; 
    if (match.innerText) { // IE 
     content += match.innerText + ' '; 
    } else if (match.textContent) { // other browsers 
     content += match.textContent + ' '; 
    } 
} 

not() 지원 선택자의 구문은 $(':not(script)') 일 뿐이니까?당신은 (일반적으로 눈에 띄는 부작용이없는 것)을 <script> 요소를 제거하기 위해 DOM을 변경할 수 있습니다 경우

+0

감사 prodigitalson - 잘 모르겠어요 그래도 내 목표를 달성 할 수있을 것입니다. 내 코드 예제에서 약간 모호했을 수도있다. CSS 노드는 CSS 선택기 배열을 가로 지르며 DOM 노드와 일치하는 각 요소에 대해 innerText (IE) 또는 textContent (other)를 가져온다. 그 노드의 속성. 실제로 요소의 자식을 통해 반복하지 않습니다. 그러나 후자가 가장 좋은 방법이라고 생각합니다. 일치하는 요소의 모든 자손을 반복하면서 텍스트 노드를 무시합니다.