我当前的项目涉及根据提供的选择器从元素及其所有后代收集文本内容。
例如,当提供选择器#content
并针对此HTML运行时:
<div id="content">
<p>This is some text.</p>
<script type="text/javascript">
var test = true;
</script>
<p>This is some more text.</p>
</div>
我的脚本将返回(经过一些小空格清理):
这是一些文字。 var test = true;这是一些更多的文字。
但是,我需要忽略<script>
个元素中出现的文本节点。
这是我当前代码的摘录(从技术上讲,它基于一个或多个提供的选择器进行匹配):
// get text content of all matching elements
for (x = 0; x < selectors.length; x++) { // 'selectors' is an array of CSS selectors from which to gather text content
matches = Sizzle(selectors[x], document);
for (y = 0; y < matches.length; y++) {
match = matches[y];
if (match.innerText) { // IE
content += match.innerText + ' ';
} else if (match.textContent) { // other browsers
content += match.textContent + ' ';
}
}
}
它有点过于简单了,因为它只返回与提供的选择器匹配的元素(及其后代)中的所有文本节点。我正在寻找的解决方案将返回除<script>
个元素之外的所有文本节点。它不需要特别高性能,但我确实需要它最终与跨浏览器兼容。
我假设我需要以某种方式遍历与选择器匹配的元素的所有子元素,并累积除<script>
元素之外的所有文本节点;一旦它已经被整合到从所有文本节点累积的字符串中,就没有任何方法可以识别JavaScript。
我不能使用jQuery(出于性能/带宽的原因),虽然您可能已经注意到我确实使用了它的Sizzle选择器引擎,因此可以使用jQuery的选择器逻辑。
提前感谢您的帮助!
答案 0 :(得分:8)
function getTextContentExceptScript(element) {
var text= [];
for (var i= 0, n= element.childNodes.length; i<n; i++) {
var child= element.childNodes[i];
if (child.nodeType===1 && child.tagName.toLowerCase()!=='script')
text.push(getTextContentExceptScript(child));
else if (child.nodeType===3)
text.push(child.data);
}
return text.join('');
}
或者,如果您被允许更改DOM以删除<script>
元素(通常不会产生明显的副作用),请更快:
var scripts= element.getElementsByTagName('script');
while (scripts.length!==0)
scripts[0].parentNode.removeChild(scripts[0]);
return 'textContent' in element? element.textContent : element.innerText;
答案 1 :(得分:2)
修改强>:
首先让我说我不太熟悉Sizzle的寂寞,jsut在使用它的图书馆......那说...
如果我必须这样做,我会做类似的事情:
var selectors = new Array('#main-content', '#side-bar');
function findText(selectors) {
var rText = '';
sNodes = typeof selectors = 'array' ? $(selectors.join(',')) : $(selectors);
for(var i = 0; i < sNodes.length; i++) {
var nodes = $(':not(script)', sNodes[i]);
for(var j=0; j < nodes.length; j++) {
if(nodes[j].nodeType != 1 && node[j].childNodes.length) {
/* recursion - this would work in jQ not sure if
* Sizzle takes a node as a selector you may need
* to tweak.
*/
rText += findText(node[j]);
}
}
}
return rText;
}
我没有测试任何这个,但它应该给你一个想法。希望其他人能够获得更多方向: - )
你不能抓住父节点并检查循环中的nodeName
......如:
if(match.parentNode.nodeName.toLowerCase() != 'script' && match.nodeName.toLowerCase() != 'script' ) {
match = matches[y];
if (match.innerText) { // IE
content += match.innerText + ' ';
} else if (match.textContent) { // other browsers
content += match.textContent + ' ';
}
}
ofcourse jquery支持选择器中的not()
语法,所以你可以$(':not(script)')
吗?