簡體   English   中英

如何獲取至少有一個直接子文本節點的元素

[英]How to get elements that have at least one direct child text node

我正在嘗試編寫一個 function 返回所有帶有直接子文本節點的元素 -

function getAllElementsWithDirectTextNode() {
    var matchingElements = [];
    var allElements = document.body.getElementsByTagName('*');
    for (var i = 0, n = allElements.length; i < n; i++) {
         if (allElements[i].childNodes !== null) {
             matchingElements.push(allElements[i]);
         }
    }
    console.log(allElements);           
}

但是,這是行不通的。 我認為這與第 5 行(if 語句)有關。 如果該元素沒有直接文本節點子節點,但確實有一個直接元素子節點,它有自己的子文本,我不想包含它。

編輯:我使用以下 DOM 嘗試了 Praveen Kumar 的解決方案,控制台打印了正文中的所有元素。 但是,我原以為只會看到 div.div1、span.span2、div.div3 和按鈕。 難道我做錯了什么?

<div class="div1">
   this is direct text
   <span class="span1"></span>
</div>
<div class="div2">
    <span class="span2">this is span text</span>
</div>
<article></article>
<div class="div3">
    <span class="span3"></span>
    this is direct text, child #2
</div>

您需要檢查它們是否具有nodeTypeNode.TEXT_NODEchildNode

function getAllElementsWithDirectTextNode() {
  var matchingElements = [];
  var allElements = document.body.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].childNodes !== null) {
      for (var j in allElements[i].childNodes)
        if (allElements[i].childNodes[j].nodeType == Node.TEXT_NODE) {
          matchingElements.push(allElements[i]);
          break;
        }
    }
  }
  console.log(allElements);           
}

您需要測試是否有任何子節點是文本節點。 因此,您需要遍歷所有孩子,測試他們的類型。

function getAllElementsWithDirectTextNode() {
  var matchingElements = [];
  var allElements = document.body.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].childNodes !== null) {
      var children = allElements[i].childNodes;
      for (var j = 0, m = children.length; j < m; j++) {
        if (children[j].nodeType == Node.TEXT_NODE) {
          matchingElements.push(allElements[i]);
          break; // don't need to check the remaining children
        }
      }
    }
  }
  console.log(allElements);
}

jsfiddle與NodeIterator

MDN參考

$(function () {
var textNodeIterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_TEXT,

function (node) {
    if (is_ignorable(node)) return NodeFilter.FILTER_REJECT;
    return NodeFilter.FILTER_ACCEPT;
});
var matchingElements = [];
var currentNode;

while (currentNode = textNodeIterator.nextNode()) {
    //console.log(currentNode);
    if (currentNode) {
        //console.log(currentNode.nodeType + "-" + currentNode.textContent);
        if (!isParentAlreadyMatched(currentNode.parentNode)) matchingElements.push(currentNode.parentNode);
    }
}
console.log(matchingElements);

function is_all_ws(nod) {
    // Use ECMA-262 Edition 3 String and RegExp features
    return !(/[^\t\n\r ]/.test(nod.textContent));
}

function is_ignorable(nod) {
    return (nod.nodeType == 8) || // A comment node
    ((nod.nodeType == 3) && is_all_ws(nod)); // a text node, all ws
}

function isParentAlreadyMatched(parentNode) {
    for (var i = 0; i < matchingElements.length; i++) {
        if (matchingElements[i] === parentNode) return true;
    }
    return false;
}
});

jsfiddle with for循環解決方案

 function getAllElementsWithDirectTextNode() {
    var matchingElements = [];
    var allElements = document.body.getElementsByTagName('*');
    for (var i = 0; i < allElements.length; i++) {
        for (var j=0; j < allElements[i].childNodes.length; j++) {
            if (allElements[i].childNodes[j].nodeType === Node.TEXT_NODE) {
                if (is_all_ws(allElements[i].childNodes[j])) continue;
                matchingElements.push(allElements[i]);
                break;
            }
        }
    }
    console.log(matchingElements);
}

function is_all_ws(nod) {
   // Use ECMA-262 Edition 3 String and RegExp features
   return !(/[^\t\n\r ]/.test(nod.textContent));
}

到目前為止提供的答案都很好,但有點過時了。 您現在可以使用一些現代 ECMAScript 和 DOM 功能:

const getAllElementsWithDirectTextNode = () => Array.from(document.body.querySelectorAll("*"))
  .filter(({ childNodes }) => Array.from(childNodes)
    .some(({ nodeType, textContent }) => nodeType === Node.TEXT_NODE && textContent.trim()))

.trim檢查用於測試從文本節點的兩端刪除空格是否仍會產生非空字符串。 如果您還想包含僅包含空格的結果,請將其刪除:

const getAllElementsWithDirectTextNode = () => Array.from(document.body.querySelectorAll("*"))
  .filter(({ childNodes }) => Array.from(childNodes)
    .some(({ nodeType }) => nodeType === Node.TEXT_NODE))

Node.prototype.childNodes getter永遠不會返回null ,因此與null的任何比較都是多余的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM