获取位于 </body> 和 </html> 之间的 HTML 评论内容的最可靠方法是什么?
What's the most reliable way to get the contents of an HTML comment located between </body> and </html>?
我正在尝试获取页面上最后 HTML 评论的内容 -- 它包含一些由 Web 应用程序服务器写入的会话信息。它写在 </html>
标签之前。在读完这个问题 (Selecting HTML Comments with jQuery) 后,我们想出了一些可行但不一致的方法:
var commentString = $("*").contents().filter(function(){
return this.nodeType == 8 ? this.nodeValue.indexOf("Expected Comment Text") > -1: false;
})[0].nodeValue;
问题是,如果页面包含 iframe(来自不同的域),* 选择器将命中它,然后我们就会被跨源策略阻止。我们可以将此选择器更改为 $("body")
,它似乎适用于大多数浏览器,但这似乎依赖于浏览器将注释移动到 body 节点内,我不相信这种情况会普遍存在。
如有必要,我们可以使用 jQuery 1.7.2(但没有插件),良好的浏览器支持 (IE < 9) 很重要。
在没有 jQuery "in reverse" 的情况下遍历 DOM 直到我们遇到 nodeType === 8
是否最好?这样,浏览器将评论节点作为 <html>
或 <body>
的子节点并不重要,只要它是文档节点树中的最后一条评论即可。这会是什么样子? (我的DOM-遍历符不行。)
你为什么不使用
$("*").not("iframe")
作为选择器,如果其余代码工作正常并且 iframe
是唯一导致问题的元素?
var commentString = $("*").not("iframe").contents().filter(function(){
return this.nodeType == 8 ? this.nodeValue.indexOf("Expected Comment Text") > -1: false;
})[0].nodeValue;
如果您采用您正在尝试的那种解决方案,将会有相当多的开销。
通过制作一个简单的、可重复使用的函数来完成 DOM。
function walk(node, cb) {
cb(node);
if (node.childNodes) {
for (var i = 0; i < node.childNodes.length; i++) {
walk(node.childNodes[i], cb);
}
}
}
// And use it like this:
walk(document, function(node) {
if (node.nodeType === 8) {
// do something with comment
alert(node.data);
}
});
<div>
foo
<iframe src="http://www.linuxmint.com"></iframe>
<!-- some comment -->
</div>
这种方式更加高效和灵活。
这是 walk
函数的另一个变体,它不使用计数器循环。
function walk(node, cb) {
cb(node);
if (node = node.firstChild) {
do walk(node, cb);
while (node = node.nextSibling)
}
}
这样更短更清晰。
如果你正在寻找 return 单个节点,那么你可以让你的回调以及递归调用 return 一个值,然后 return 当值实际上是 returned.
根据您的评论,此版本倒退了 DOM。
function walk(node, cb) {
var res = cb(node);
if (res)
return res;
if (node = node.lastChild) {
do if (res = walk(node, cb))
return res;
while (node = node.previousSibling)
}
}
var result = walk(document, function(node) {
if (node.nodeType === 8) {
return node;
}
});
if (result)
alert(result.data);
<div>
foo
<!-- Some other comment -->
<iframe src="http://www.linuxmint.com"></iframe>
<!-- Success! - Expected Comment Text -->
</div>
我正在尝试获取页面上最后 HTML 评论的内容 -- 它包含一些由 Web 应用程序服务器写入的会话信息。它写在 </html>
标签之前。在读完这个问题 (Selecting HTML Comments with jQuery) 后,我们想出了一些可行但不一致的方法:
var commentString = $("*").contents().filter(function(){
return this.nodeType == 8 ? this.nodeValue.indexOf("Expected Comment Text") > -1: false;
})[0].nodeValue;
问题是,如果页面包含 iframe(来自不同的域),* 选择器将命中它,然后我们就会被跨源策略阻止。我们可以将此选择器更改为 $("body")
,它似乎适用于大多数浏览器,但这似乎依赖于浏览器将注释移动到 body 节点内,我不相信这种情况会普遍存在。
如有必要,我们可以使用 jQuery 1.7.2(但没有插件),良好的浏览器支持 (IE < 9) 很重要。
在没有 jQuery "in reverse" 的情况下遍历 DOM 直到我们遇到 nodeType === 8
是否最好?这样,浏览器将评论节点作为 <html>
或 <body>
的子节点并不重要,只要它是文档节点树中的最后一条评论即可。这会是什么样子? (我的DOM-遍历符不行。)
你为什么不使用
$("*").not("iframe")
作为选择器,如果其余代码工作正常并且 iframe
是唯一导致问题的元素?
var commentString = $("*").not("iframe").contents().filter(function(){
return this.nodeType == 8 ? this.nodeValue.indexOf("Expected Comment Text") > -1: false;
})[0].nodeValue;
如果您采用您正在尝试的那种解决方案,将会有相当多的开销。
通过制作一个简单的、可重复使用的函数来完成 DOM。
function walk(node, cb) {
cb(node);
if (node.childNodes) {
for (var i = 0; i < node.childNodes.length; i++) {
walk(node.childNodes[i], cb);
}
}
}
// And use it like this:
walk(document, function(node) {
if (node.nodeType === 8) {
// do something with comment
alert(node.data);
}
});
<div>
foo
<iframe src="http://www.linuxmint.com"></iframe>
<!-- some comment -->
</div>
这种方式更加高效和灵活。
这是 walk
函数的另一个变体,它不使用计数器循环。
function walk(node, cb) {
cb(node);
if (node = node.firstChild) {
do walk(node, cb);
while (node = node.nextSibling)
}
}
这样更短更清晰。
如果你正在寻找 return 单个节点,那么你可以让你的回调以及递归调用 return 一个值,然后 return 当值实际上是 returned.
根据您的评论,此版本倒退了 DOM。
function walk(node, cb) {
var res = cb(node);
if (res)
return res;
if (node = node.lastChild) {
do if (res = walk(node, cb))
return res;
while (node = node.previousSibling)
}
}
var result = walk(document, function(node) {
if (node.nodeType === 8) {
return node;
}
});
if (result)
alert(result.data);
<div>
foo
<!-- Some other comment -->
<iframe src="http://www.linuxmint.com"></iframe>
<!-- Success! - Expected Comment Text -->
</div>