简体   繁体   中英

How can I translate jQuery ':not(:has(*)):not(a *):not(a)' to pure js for the TreeWalker?

I need to exclude some text node. For that I used

$('body :not(:has(*)):not(script):not(textarea):not(textarea *):not(a *):not(a)')

The function I use is:

function findAllTextNodes(n) {
  var walker = n.ownerDocument.createTreeWalker(n, NodeFilter.SHOW_TEXT);
  var textNodes = [];
  while (walker.nextNode())
    if (walker.currentNode.parentNode.tagName != 'SCRIPT' && 
  walker.currentNode.parentNode.tagName != 'A' && walker.currentNode.parentNode.className != 'to-ignore')
      textNodes.push(walker.currentNode);
  return textNodes;
}

Is there a nicer, more readable way to do it and how do I do the ':not(:has(*))' or ':not(a *)'?

Edit: Don't have the link to the original post, but here the link to jsfiddle I also don't want the 'the' inside <a> and <span> to be replaced.

The Document.createTreeWalker constructor can include aNodeFilter object with an filter function that tests each node selected by the whatToShow parameter.

For nodes that pass the test, the filter function should return the value NodeFilter.FILTER_ACCEPT .

When testing the nodes, you can use the matches(selectorList) method from the DOM Element API with a list of selectors that you don't want to match. Either use a simple list and negate the result (as in the example), or use the :not(selectorList) pseudo–class .

The following also filters out empty text nodes and those with only whitespace, since many browsers will insert empty text nodes where the HTML source has any whitespace between element tags (eg <p></p> may have from zero to three empty text nodes when parsed depending on surrounding code). It also pushes the actual text into the array rather than the text node objects.

 function findTextNodes() { var walker = document.createTreeWalker( document.body, // root NodeFilter.SHOW_TEXT, // nodes to include {acceptNode: filter} // NodeFilter object ); var textNodes = []; while (walker.nextNode()) { textNodes.push(walker.currentNode.textContent); } return textNodes; } // NodeFilter function function filter(node) { // Ignore any node that matches a selector in the list // and nodes that are empty or only whitespace if (!node.parentNode.matches('a, a *, script, textarea, .to-ignore') && !/^\\s*$/.test(node.textContent) ) { // If passes test, return accept value return NodeFilter.FILTER_ACCEPT; } } let textNodes = findTextNodes(); console.log(textNodes.join('\\n'));
 .to-ignore { background-color: yellow; } a * { color: green; }
 <p>It's the end of the world as we know it,<br> and I feel fine</p> <a>the in a</a> <br> <a><span>the in span in a</span></a> <span class="to-ignore">in to-ignore</span>

Nodes that will be ignored by the filter function are those that match any of the following selectors:

  1. a - A elements
  2. a * - all descendants of A elements
  3. script - script elements
  4. textarea - textarea elements
  5. .to-ignore - elements with class "to-ignore"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM