[英]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>
您需要檢查它們是否具有nodeType
為Node.TEXT_NODE
的childNode
:
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);
}
$(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;
}
});
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.