6

私の現在のプロジェクトでは、提供されたセレクターに基づいて、要素とそのすべての子孫からテキストコンテンツを収集します。

たとえば、セレクター#contentを指定してこのHTMLに対して実行すると、次のようになります。

<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>

私のスクリプトは(少し空白をクリーンアップした後)返されます:

これはいくつかのテキストです。var test = true; これはもう少しテキストです。

<script>ただし、要素内にあるテキストノードは無視する必要があります。

これは私の現在のコードの抜粋です(技術的には、1つ以上の提供されたセレクターに基づいて一致します):

// 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がすでに組み込まれていると、JavaScriptを識別する方法はないようです。

(パフォーマンス/帯域幅の理由で)jQueryを使用できませんが、Sizzleセレクターエンジンを使用していることに気付いたかもしれません。そのため、jQueryのセレクターロジックを使用できます。

助けてくれてありがとう!

4

2 に答える 2

9
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('');
}

または、DOM を変更して<script>要素を削除することが許可されている場合 (通常は顕著な副作用はありません)、より迅速に:

var scripts= element.getElementsByTagName('script');
while (scripts.length!==0)
    scripts[0].parentNode.removeChild(scripts[0]);
return 'textContent' in element? element.textContent : element.innerText;
于 2010-03-28T10:06:16.923 に答える
2

編集

まず最初に、Sizzle を使用するライブラリ内の jsut の寂しい点について、私は Sizzle にあまり慣れていないと言わせてください。

私がこれをしなければならなかった場合、私は次のようなことをします:

var selectors = new Array('#main-content', '#side-bar');
function findText(selectors) {
    var rText = '';
    sNodes = typeof selectors = 'array' ? $(selectors.join(',')) : $(selectors);
    for(var i = 0; i <  sNodes.length; i++) {
       var nodes = $(':not(script)', sNodes[i]);
       for(var j=0; j < nodes.length; j++) {
         if(nodes[j].nodeType != 1 && node[j].childNodes.length) {
             /* recursion - this would work in jQ not sure if 
              * Sizzle takes a node as a selector you may need 
              * to tweak.
              */
             rText += findText(node[j]); 
         }  
       }
    }

    return rText;
}

私はそれをテストしませんでしたが、それはあなたにアイデアを与えるはずです. うまくいけば、他の誰かがより多くの方向性を示してくれるでしょう:-)


親ノードをつかんでnodeNameループ内をチェックするだけではいけません...のように:

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 + ' ';
    }
}

もちろん、jqueryはnot()セレクターの構文をサポートしているので、できます$(':not(script)')か?

于 2010-03-28T06:40:27.687 に答える