window.onload = function() {
var sl = new socialhistory();
alert(sl.doesvisit(www.jb51.net));
}
如果用户曾经使用过www.jb51.net,那么该函数就会返回真,否则返回假。
其实原理并不复杂,它利用了链接的 a:visited 伪类的属性。首先在页面上生成一个iframe,并在这个iframe中设置 a 和 a:visited 为不同的样式。然后将网站的链接插入到 iframe 中。浏览器就会根据用户的访问历史,为访问过的链接设置 a:visited 的样式。最后再获得链接的最终样式,如果是 a:visited,就可以认为用户访问过该网站了。具体的实现方式可以参考源代码。
这个脚本主要用于显示社会性书签的图标,可以恰到好处地显示用户所使用的网站。但我担心,这样的做法是不是有盗取用户隐私之嫌?虽然这个方法只能判断用户有无访问特定的网站,并不能无限制地得到所有访问历史。
/*
* social limit - only the social you care about.
*
* enables your site to know which social bookmarking badges to display to your
* visitors. it tells you all social sites the user has gone to, or you can
* query for a specific one.
*
* for example:
*
* var sl = socialhistory();
* alert( sl.doesvisit(digg) ); // returns true/false, -1 if unknown.
* var listofvisitedsites = sl.visitedsites();
* var checkedsites = sl.checkedsites();
*
* if you want to add more sites to check, you can pass that in as a dictionary
* to history:
*
* var more = { humanized: http://humanized.com,
* azarask.in: [http://azarask.in, http://azarask.in/blog]
* };
* var sl = socialhistory(more);
* alert( sl.doesvisit(humanized) );
*
* for a list of built-in sites, see the sites variable below.
*
* copyright (c) 2008 aza raskin (http://azarask.in/blog)
*
* permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the software), to deal
* in the software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the software, and to permit persons to whom the software is
* furnished to do so, subject to the following conditions:
*
* the above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the software.
*
* the software is provided as is, without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. in no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the software or the use or other dealings in
* the software.
*
*/
var socialhistory = function( moresites ){
var sites = {
digg: [http://digg.com, http://digg.com/login],
reddit: [http://reddit.com, http://reddit.com/new/, http://reddit.com/controversial/, http://reddit.com/top/, http://reddit.com/r/reddit.com/, http://reddit.com/r/programming/],
stumbleupon: [http://stumbleupon.com],
yahoo buzz: [http://buzz.yahoo.com],
facebook: [http://facebook.com/home.php, http://facebook.com, https://login.facebook.com/login.php],
del.icio.us: [https://secure.del.icio.us/login, http://del.icio.us/],
myspace: [http://www.myspace.com/],
technorati: [http://www.technorati.com],
newsvine: [https://www.newsvine.com, https://www.newsvine.com/_tools/user/login],
songza: [http://songza.com],
slashdot: [http://slashdot.org/],
ma.gnolia: [http://ma.gnolia.com/],
blinklist: [http://www.blinklist.com],
furl: [http://furl.net, http://furl.net/members/login],
mister wong: [http://www.mister-wong.com],
current: [http://current.com, http://current.com/login.html],
menaeme: [http://meneame.net, http://meneame.net/login.php],
oknotizie: [http://oknotizie.alice.it, http://oknotizie.alice.it/login.html.php],
diigo: [http://www.diigo.com/, https://secure.diigo.com/sign-in],
funp: [http://funp.com, http://funp.com/account/loginpage.php],
blogmarks: [http://blogmarks.net],
yahoo bookmarks: [http://bookmarks.yahoo.com],
xanga: [http://xanga.com],
blogger: [http://blogger.com],
last.fm: [http://www.last.fm/, https://www.last.fm/login/],
n4g: [http://www.n4g.com],
faves: [http://faves.com, http://faves.com/home, https://secure.faves.com/signin],
simpy: [http://www.simpy.com, http://www.simpy.com/login],
yigg: [http://www.yigg.de],
kirtsy: [http://www.kirtsy.com, http://www.kirtsy.com/login.php],
fark: [http://www.fark.com, http://cgi.fark.com/cgi/fark/users.pl?self=1],
mixx: [https://www.mixx.com/login/dual, http://www.mixx.com],
google bookmarks: [http://www.google.com/bookmarks, http://www.google.com/ig/add?moduleurl=bookmarks.xml&hl=en],
subbmitt: [http://subbmitt.com/]
};
for( var site in moresites ) {
// if we don't have the site, create the url list.
if( typeof( sites[site] ) == undefined ) sites[site] = [];
// if the value is string, just push that onto the url list.
if( typeof( moresites[site] ) == string )
sites[site].push( moresites[site] );
else
sites[site] = sites[site].concat( moresites[site] );
}
var visited = {};
function getstyle(el, scopedoc,styleprop) {
if (el.currentstyle)
var y = el.currentstyle[styleprop];
else if (window.getcomputedstyle)
var y = scopedoc.defaultview.getcomputedstyle(el,null).getpropertyvalue(styleprop);
return y;
}
function remove( el ) {
el.parentnode.removechild( el );
}
// code inspired by:
// bindzus.wordpress.com/2007/12/24/adding-dynamic-contents-to-iframes
function createiframe() {
var iframe = document.createelement(iframe);
iframe.style.position = absolute;
iframe.style.visibility = hidden;
document.body.appendchild(iframe);
// firefox, opera
if(iframe.contentdocument) iframe.doc = iframe.contentdocument;
// internet explorer
else if(iframe.contentwindow) iframe.doc = iframe.contentwindow.document;
// magic: force creation of the body (which is null by default in ie).
// also force the styles of visited/not-visted links.
iframe.doc.open();
iframe.doc.write(');
iframe.doc.write(a{color: #000000; display:none;});
iframe.doc.write(a:visited {color: #ff0000; display:inline;});
iframe.doc.write('');
iframe.doc.close();
// return the iframe: iframe.doc contains the iframe.
return iframe;
}
var iframe = createiframe();
function embedlinkiniframe( href, text ) {
var a = iframe.doc.createelement(a);
a.href = href;
a.innerhtml = site;
iframe.doc.body.appendchild( a );
}
for( var site in sites ) {
var urls = sites[site];
for( var i=0; iurls.length; i++ ) {
// you have to create elements in the scope of the iframe for ie.
embedlinkiniframe( urls[i], site );
// automatically try variations of the urls with and without the www
if( urls[i].match(/www\./) ){
var sanswww = urls[i].replace(/www\./, );
embedlinkiniframe( sanswww, site );
} else {
// 2 = 1 for length of string + 1 for slice offset
var httplen = urls[i].indexof(//) + 2;
var withwww = urls[i].substring(0, httplen ) + www. + urls[i].substring( httplen );
embedlinkiniframe( withwww, site );
}
}
}
var links = iframe.doc.body.childnodes;
for( var i=0; ilinks.length; i++) {
// handle both firefox/safari, and ie (respectively)
var displayvalue = getstyle(links[i], iframe.doc, display);
var didvisit = displayvalue != none;
if( didvisit ){
visited[ links[i].innerhtml ] = true;
}
}
remove( iframe );
return new (function(){
var usedsites = [];
for( var site in visited ){
usedsites.push( site );
}
// return an array of visited sites.
this.visitedsites = function() {
return usedsites;
}
// return true/false. if we didn't check the site, return -1.
this.doesvisit = function( site ) {
if( typeof( sites[site] ) == undefined )
return -1;
return typeof( visited[site] ) != undefined;
}
var checkedsites = [];
for( var site in sites ){
checkedsites.push( site );
}
// return a list of the sites checked.
this.checkedsites = function(){
return checkedsites;
}
})();
}