如何使`.innerText`忽略不可见元素的隐形子元素?

时间:2017-03-28 03:49:18

标签: javascript innertext

以下测试代码的结果:

div[0].innerText === "aaaaa zzzzz"
div[1].innerText === "␤aaaaa␤invisible␤zzzzz␤"

如何强制innerTextdiv[1]提供与div[0]相同的结果?

我已尝试将div[1]附加到临时文档中,但由于文档实际上未显示,因此无效。只将它附加到字面上可见的文档。

测试代码



var div = [];
div[0] = document.getElementById("visible");
div[1] = div[0].cloneNode(true);

show(0);
show(1);

function show(i) {
    document.getElementById("output").innerHTML += 
      "<p>div[" + i + "].innerText === <code>" + 
      div[i].innerText.replace(/\n/g, "␤") + "</code></p>";
}
&#13;
#visible {display: block; font-family: sans-serif; font-size: larger; color: red;}
code {background-color: lightgray; padding: 0 .318em;}
&#13;
<div id="visible">
<span style="display: inline">aaaaa</span>
<span style="display: none">invisible</span>
<span style="display: inline">zzzzz</span>
</div>

<div id="output"></p>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

  

仅将其附加到用户可见的文档中。

但是用户并不一定要看到这一点。 :-)如果你追加它,抓住innerText,然后删除它,用户永远不会看到它:

&#13;
&#13;
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]);  // *****

function show(i) {
    document.getElementById("output").innerHTML += 
      "<p>div[" + i + "].innerText === <code>" + 
      div[i].innerText.replace(/\n/g, "␤") + "</code></p>";
}
&#13;
#visible {display: block; font-family: sans-serif; font-size: larger; color: red;}
code {background-color: lightgray; padding: 0 .318em;}
&#13;
<div id="visible">
<span style="display: inline">aaaaa</span>
<span style="display: none">invisible</span>
<span style="display: inline">zzzzz</span>
</div>

<div id="output"></p>
&#13;
&#13;
&#13;

或者,由于元素不在DOM中,因此CSS不能使其不可见,只能是内联样式。我无法想到除了innerTextdisplay: nonevisibility: hidden之外的任何其他内联样式会导致文本被排除在opacity: 0之外,例如,没有做到这一点,所以排除那些并规范化非pre元素的空白是微不足道的:

function getInnerText(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;
      } else if (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;
}

这可能需要调整(我不认为它能正确处理<div>stuff<pre>big gap</pre></div>),但如果你不想使用上面的第一个解决方案,你可以运行这个想法......

示例:

&#13;
&#13;
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]);  // *****

function show(i) {
    document.getElementById("output").innerHTML += 
      "<p>div[" + i + "].innerText === <code>" + 
      getInnerText(div[i]).replace(/\n/g, "␤") + "</code></p>";
}

function getInnerText(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;
      } else if (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;
}
&#13;
#visible {display: block; font-family: sans-serif; font-size: larger; color: red;}
code {background-color: lightgray; padding: 0 .318em;}
&#13;
<div id="visible">
<span style="display: inline">aaaaa</span>
<span style="display: none">invisible</span>
<span style="display: inline">zzzzz</span>
</div>

<div id="output"></p>
&#13;
&#13;
&#13;