How Can I Make `.innertext` Ignore Invisible Children Of An Invisible Element?
Solution 1:
Only appending it to a document literally visible to the user works.
But the user doesn't necessarily have to see that. :-) If you append it, grab innerText
, and then remove it, the user will never see it:
var div = [];
div[0] = document.getElementById("visible");
div[1] = div[0].cloneNode(true);
show(0);
document.body.appendChild(div[1]); // *****show(1);
document.body.removeChild(div[1]); // *****functionshow(i) {
document.getElementById("output").innerHTML +=
"<p>div[" + i + "].innerText === <code>" +
div[i].innerText.replace(/\n/g, "") + "</code></p>";
}
#visible {display: block; font-family: sans-serif; font-size: larger; color: red;}
code {background-color: lightgray; padding: 0 .318em;}
<divid="visible"><spanstyle="display: inline">aaaaa</span><spanstyle="display: none">invisible</span><spanstyle="display: inline">zzzzz</span></div><divid="output"></p>
Alternately, since the element isn't in the DOM, it can't be made invisible by CSS, only inline styles. I can't think of any other inline style that would make the text get left out of innerText
other than your display: none
and visibility: hidden
(opacity: 0
, for instance, doesn't do it), so it's trivial to exclude those and normalize whitespace for non-pre
elements:
functiongetInnerText(element) {
var node, text = "";
if (element.style.display.toLowerCase() !== "none" && element.style.visibility.toLowerCase() !== "hidden") {
for (node = element.firstChild; node; node = node.nextSibling) {
if (node.nodeType === 3) {
text += node.nodeValue;
} elseif (node.nodeType === 1) {
text += getInnerText(node);
}
}
}
// Normalize all whitespace if not "pre"if (element.tagName !== "PRE" && element.style.whiteSpace.toLowerCase().indexOf("pre") == -1) {
text = text.replace(/\s+/g, ' ');
}
return text;
}
That may well need tweaking (I don't think it handles <div>stuff<pre>big gap</pre></div>
properly), but you can run with the idea if you don't want to use the first solution above...
Example:
var div = [];
div[0] = document.getElementById("visible");
div[1] = div[0].cloneNode(true);
show(0);
document.body.appendChild(div[1]); // *****show(1);
document.body.removeChild(div[1]); // *****functionshow(i) {
document.getElementById("output").innerHTML +=
"<p>div[" + i + "].innerText === <code>" +
getInnerText(div[i]).replace(/\n/g, "") + "</code></p>";
}
functiongetInnerText(element) {
var node, text = "";
if (element.style.display.toLowerCase() !== "none" && element.style.visibility.toLowerCase() !== "hidden") {
for (node = element.firstChild; node; node = node.nextSibling) {
if (node.nodeType === 3) {
text += node.nodeValue;
} elseif (node.nodeType === 1) {
text += getInnerText(node);
}
}
}
// Normalize all whitespace if not "pre"if (element.tagName !== "PRE" && element.style.whiteSpace.toLowerCase().indexOf("pre") == -1) {
text = text.replace(/\s+/g, " ");
}
return text;
}
#visible {display: block; font-family: sans-serif; font-size: larger; color: red;}
code {background-color: lightgray; padding: 0 .318em;}
<divid="visible"><spanstyle="display: inline">aaaaa</span><spanstyle="display: none">invisible</span><spanstyle="display: inline">zzzzz</span></div><divid="output"></p>
Post a Comment for "How Can I Make `.innertext` Ignore Invisible Children Of An Invisible Element?"