[英]CSS/JavaScript/hacking: Detect :visited styling on a link *without* checking it directly OR do it faster than me
这是出于研究目的http://cssfingerprint.com
请考虑以下代码:
<style>
div.csshistory a { display: none; color: #00ff00;}
div.csshistory a:visited { display: inline; color: #ff0000;}
</style>
<div id="batch" class="csshistory">
<a id="1" href="http://foo.com">anything you want here</a>
<a id="2" href="http://bar.com">anything you want here</a>
[etc * ~2000]
</div>
我的目标是检测foo是否已使用:visited样式呈现。
我想检测是否访问foo.com 而不直接查看$('1').getComputedStyle
(或在Internet Explorer, currentStyle
)或该元素上的任何其他直接方法。
这样做的目的是绕过潜在的浏览器限制,以防止直接检查访问链接的样式。
例如,也许你可以在<a>
标签中放置一个子元素,或者直接检查文本的样式; 任何不直接或间接依赖$('1').anything
都是可以接受的。 做一些聪明的孩子或父母可能是必要的。
请注意,仅出于此目的,场景是浏览器将谎言JavaScript关于<a>
元素的所有属性(而不是其他属性),并且它将仅呈现color:
in :visited
。 因此,依赖于例如文本大小或background-image
将不满足该要求。
我想提高目前刮削方法的速度。
大部分时间(至少使用Firefox中的jQuery方法)花费在document.body.appendChild(batch)
,因此找到改进该调用的方法可能是最有效的。
有关当前速度测试结果,请参见http://cssfingerprint.com/about和http://cssfingerprint.com/results 。
我目前使用的方法可以在http://github.com/saizai/cssfingerprint/blob/master/public/javascripts/history_scrape.js上看到。
总结tl; dr,它们是:
getComputedStyle
检查每一个 <a>
标签内,并使用jQuery的:visible选择器,只提取可见文本(=访问过的链接ID) FWIW,我是一个白帽子 ,我正在与EFF以及其他一些众所周知的安全研究人员协商。
如果你贡献一种新的方法或加速,你会感谢http://cssfingerprint.com/about (如果你想成为:-P),并可能在未来发表的论文中。
ETA:赏金只会因为建议而获得奖励
如果多个建议符合任何一个标准,那么最好的建议就会胜出。
ETA 2:我添加了两个以前最好的测试方法的基于宽度的变体(reuse_noinsert,最好的Firefox / Mozilla和mass_insert,它非常接近的竞争对手)。 请从不同的浏览器访问http://cssfingerprint.com几次; 我会自动获得速度测试结果,因此我们会发现它是否比以前的方法更好,如果是这样的话。 谢谢!
ETA 3:目前的测试表明,使用offsetWidth
(1.8%)的offsetWidth
(而不是getCalculatedStyle
/ currentStyle
)和Firefox中的~24ms(4.3%)可以节省速度,这不是我想要的10%的实力奖励赢得。 知道如何维持剩余的10%?
[新更新]
如果您希望结果仅用于视觉呈现,那么最快的方法是使用CSS计数器。
CSS:
body{
counter-reset: visited_counter;
}
a:visited{
counter-increment: visited_counter;
}
#results:before{
content:counter(visited_counter);
}
这将在id为'results'的元素之前添加已访问链接的数量。
不幸的是,没有办法从JavaScript访问它,你只能显示它..
[初答]
你知道jQuery直接支持:visited
选择器吗?
喜欢$('a:visited')
[更新]
作为替代方案,您可以应用不依赖于getComputedStyle
来检索的CSS属性。
像a:visited{height:1px;display:block;}
然后检查offsetHeight
。
color : inherit
警告:afaik它不会对lte ie7起作用
对于lte ie7 ull必须
visibility : hidden
在a:visited
和visibility : inherit
孩子 一个类似的想法,但回避.getComputedStyle()
:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style type="text/css">
a:visited { display: inline-block; font-family: monospace; }
body { font-family: sans-serif; }
</style>
<script type="text/javascript">
function test() {
var visited = document.getElementById("v").childNodes[1].firstChild.clientWidth;
var unvisited = document.getElementById("u").childNodes[1].firstChild.clientWidth;
var rows = document.getElementsByTagName("tr");
for (var i = 1, length = rows.length; i < length; i++) {
var row = rows[i];
var link = row.childNodes[1].firstChild;
var width = link.clientWidth;
row.firstChild.appendChild(document.createTextNode(link.href));
row.childNodes[2].appendChild(document.createTextNode(width === visited ? "yes" : (width === unvisited ? "no" : "unknown")));
}
}
</script>
</head>
<body onload="test()">
<table>
<tr><th>url</th><th>link</th><th>visited?</th></tr>
<tr id="u"><td></td><td><a href="http://invalid_host..mplx/">l</a></td><td></td>
<tr id="v"><td></td><td><a href="css-snoop.html">l</a></td><td></td>
<tr><td></td><td><a href="http://stackoverflow.com/">l</a></td><td></td>
<tr><td></td><td><a href="http://www.dell.com/">l</a></td><td></td>
</table>
</body>
</html>
当然,诀窍是确保访问和未访问的链接具有不同的宽度(这里,通过使用sans-serf与monospace字体)并将它们设置为inline-block
以便可以通过clientWidth
访问它们的宽度。 经测试可用于FF3.6,IE7,Chrome 4和Opera 10。
在我的测试中,访问clientWidth
始终比依赖计算样式的任何东西都快(有时多达~40%,但差异很大)。
(哦,并为<body onload="...">
胡说八道道歉;因为我试图在没有框架的情况下在IE中做事件已经太久了,我厌倦了打架。)
由于所有版本的IE(是的,即使版本8,如果你启用怪癖)支持CSS表达式,颜色属性仍然是不安全的。 您可以用这个(未经测试)加速IE测试:
a:visited { color: expression( arrVisited.push(this.href) ); }
此问题并未真正涵盖在您的问题中,但您当然可以非常轻松地在子节点中设置属性以启动检测,并且任何解决方案都必须防止这样做:
a.google:visited span { background-image: url(http://example.com/visited/google); }
你也需要保护邻近的兄弟姐妹,而不仅仅是后代:
a.google:visited + span { }
也未经测试,但您可能使用content
属性修改DOM然后使用一些XPath来查找新节点,从而进行大量加速。
a.google:visited:before {content: "visited"; visibility: hidden;}
XPath的:
visited links = document.evaluate('//a[text()="visited"]')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.