// ==UserScript==
// @name Bloglines meets Hatena Bookmark
// @namespace http://www.m4i.jp/
// @include http://www.bloglines.com/myblogs_display?*
// @include http://www.bloglines.com/public_display?*
// @version 1.0.2
// ==/UserScript==
(function(){
Function.prototype.bind = function(object) {
var __method = this;
return function() {
return __method.apply(object, arguments);
};
};
function XMLRPC() {
this.calls = [];
this.called = 0;
this.chunk = 0;
}
XMLRPC.prototype = {
proxy: function(endPoint)
{
this.endPoint = endPoint;
return this;
},
call: function(method, params)
{
this.parts = this.chunk ? Math.ceil(params.length / this.chunk) : 1;
for (var i = 0; i < this.parts; i++) {
var call =
{method}
;
var param = this.chunk ?
params.slice(this.chunk * i, this.chunk * (i + 1)) : params;
for (var j = 0; j < param.length; j++) {
call..params.appendChild(
{param[j]}
);
}
this.calls.push(call);
}
return this;
},
result: function(callback)
{
this.callback = callback;
for (var i = 0; i < this.parts; i++) {
GM_xmlhttpRequest({
method: 'post',
url: this.endPoint,
data: this.calls[i].toString(),
onload: this._loadHandler.bind(this)
});
}
return this;
},
split: function(chunk)
{
this.chunk = chunk;
return this;
},
_loadHandler: function(res)
{
var response = new XML(res.responseText.replace(/^<\?xml.*?\?>/, ''));
if (this.response) {
this.response..struct.appendChild(response..member);
} else {
this.response = response;
}
if (++this.called == this.parts) {
this.callback(this.response);
}
}
};
var entryURI = 'http://b.hatena.ne.jp/entry/';
var endPoint = 'http://b.hatena.ne.jp/xmlrpc';
var item_expr = '//div[starts-with(@id, "siteItem.")]';
var uris = [];
var hrefs = document.evaluate(
item_expr + '/h3/a/@href', document, null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var href;
while (href = hrefs.iterateNext()) {
uris.push(href.nodeValue);
}
new XMLRPC()
.split(50)
.proxy(endPoint)
.call('bookmark.getCount', uris)
.result(function(response) {
var members = {};
for each (var member in response..member) {
members[member.name] = member..int;
}
var items = document.evaluate(
item_expr, document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < items.snapshotLength; i++) {
var uri = document.evaluate(
'./h3/a/@href', items.snapshotItem(i), null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.nodeValue;
var ul = document.evaluate(
'./div/ul[@class="item_nav"]', items.snapshotItem(i), null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
var users = members[uri];
if (!Number(users)) continue;
var a = document.createElement('a');
var li = document.createElement('li');
a.setAttribute('href', entryURI + uri.replace(/#/, '%23'));
a.setAttribute('target', '_blank');
a.setAttribute('class', users >= 10 ? 'hottest' :
users >= 5 ? 'hotter' :
'hot');
a.appendChild(document.createTextNode(
'?B: ' + users + (users == 1 ? ' user' : ' users')));
li.appendChild(a);
ul.appendChild(li);
}
});
var style = document.createElement('style');
style.setAttribute('type', 'text/css');
style.innerHTML
= '.hotter'
+ '{'
+ ' color: #ff6666 !important;'
+ ' background-color: #fff0f0;'
+ ' font-weight: bold;'
+ ' font-style: normal;'
+ '}'
+ '.hottest'
+ '{'
+ ' color: red !important;'
+ ' background-color: #ffcccc;'
+ ' font-weight: bold;'
+ ' font-style: normal;'
+ '}';
document.getElementsByTagName('head')[0].appendChild(style);
})();