// ==UserScript==
// @name Hatena bookmark hack
// @namespace http://blog.f99aq8ove.net/
// @description Mashup hatena bookmark and ... ver. 1.4
// @include http://*
// @exclude https://*
// @exclude http://flickr.com/services/auth/*
// @exclude http://auth.hatena.ne.jp/*
// ==/UserScript==
(function()
{
var encodedURI = encodeURI(document.URL).replace("#","%23"); //encodeURI(document.URL.replace(/\?.+$/, ""));
var existAPIURI = "http://d.hatena.ne.jp/exist?mode=xml&url=";
var entryURI = "http://b.hatena.ne.jp/entry/";
var appendURI = "http://b.hatena.ne.jp/append?";
var entryRSSURI = "http://b.hatena.ne.jp/entry/rss/"; //"http://b.hatena.ne.jp.nyud.net:8090/entry/rss/";
var skipURIs = Array(
"$https",
".*\b__mode=handle_sign_in\b",
"http://flickr\.com/services/auth/",
".*\bfrob=[\w-]*\b",
"\bopenid\.",
"http://auth\.hatena\.ne\.jp",
".*\bcert=[0-9A-Fa-f]{16}\b"
);
for each (var skipURI in skipURIs) {
if (document.URL.match(skipURI)) {
return;
}
}
// ----------------------------------------------------
var containerElm, toggleElm, backgroundElm, innerElm;
var gotEntryRSS = false;
var isPopup = false;
createElements();
// Get number of bookmarks using HatenaAPI
GM_xmlhttpRequest({method: "GET", url: existAPIURI + encodedURI, onload: existAPICallback});
return;
// ----------------------------------------------------
function createElements()
{
backgroundElm = document.createElement("div");
backgroundElm.id = "hatenaBookmarkHackBackground";
backgroundElm.setAttribute("style", "background:#000;height:100%;left:0;opacity:0.5;position:fixed;top:0;width:100%;z-index:50000");
backgroundElm.style.display = "none";
document.body.appendChild(backgroundElm);
containerElm = document.createElement("div");
containerElm.setAttribute("style", "-moz-border-radius:20px;background:#fff;color:#000;height:80%;left:0;margin:5%;padding:0;position:fixed;top:0;width:90%;z-index:50001");
containerElm.style.display = "none";
document.body.appendChild(containerElm);
innerElm = document.createElement("div");
innerElm.setAttribute("style", "margin:20px;height:80%;overflow-y:auto;overflow-x:hidden");
containerElm.appendChild(innerElm);
toggleElm = document.createElement("a");
toggleElm.setAttribute("style", "background:#fff;cursor:pointer;right:0;margin:0;opacity:0.8;padding:0;position:fixed;top:0;z-index:50002");
document.body.appendChild(toggleElm);
}
function existAPICallback(res)
{
var existxml = new XML(res.responseText.replace(/^<\?xml.*?\?>/, ""));
var countofBookmark = existxml.count.(@name == "bookmark");
if (countofBookmark > 0) {
toggleElm.innerHTML = "?B:" + countofBookmark;
toggleElm.addEventListener(
"click",
function() {
if (isPopup) {
containerElm.style.display = backgroundElm.style.display = "none";
isPopup = false;
} else {
if (gotEntryRSS) {
containerElm.style.display = backgroundElm.style.display = "";
isPopup = true;
} else {
// get hatena bookmark comments
toggleElm.style.color = "#888";
GM_xmlhttpRequest({
method: "GET",
url: entryRSSURI + encodedURI,
onload: function(res)
{
entryAPICallback(res);
toggleElm.style.color = "#000";
gotEntryRSS = true;
containerElm.style.display = backgroundElm.style.display = "";
isPopup = true;
},
onerror: function(){ toggleElm.style.color = "red" }});
}
}
return false;
}, true);
var elm = document.createElement("div");
elm.innerHTML = 'この記事を含むはてなブックマーク この記事をはてなブックマーク';
append(elm);
}
}
function entryAPICallback(res)
{
var rss = new XML(res.responseText.replace(/^<\?xml.*?\?>/, ""));
makeCommentsList(rss);
makeTagCloud(rss);
}
function htmlspecialchars(str)
{
return String(str).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); // "
}
function makeCommentsList(rssDoc)
{
var rss = new Namespace("http://purl.org/rss/1.0/");
var divElm = document.createElement("div");
var ulElm = document.createElement("ul");
divElm.appendChild(ulElm);
for each (var item in rssDoc.rss::item.(rss::description != "")) {
var liElm = document.createElement("li");
ulElm.appendChild(liElm);
liElm.innerHTML = ''
+ htmlspecialchars(item.rss::title) + "『"
+ htmlspecialchars(item.rss::description) + "』";
}
append(divElm);
}
function makeTagCloud(rssDoc)
{
var rss = new Namespace("http://purl.org/rss/1.0/");
var dc = new Namespace("http://purl.org/dc/elements/1.1/");
var tags = new Array();
for each (var tag in rssDoc.rss::item.dc::subject) {
if (!tags[tag]) { // oops
tags[tag] = 1;
} else {
++tags[tag];
}
}
var cloudVars = getFactor(tags);
var elm = document.createElement("div");
for (var tag in tags) {
var a = document.createElement("a");
a.appendChild(document.createTextNode(tag));
a.href = "http://b.hatena.ne.jp/t/" + encodeURIComponent(tag);
a.title = tag + ": " + tags[tag];
a.style.fontFamily = "Arial";
a.style.lineHeight = "16px";
a.style.fontSize = (12
+ Math.floor((Math.log(tags[tag]) - cloudVars["min"]) * cloudVars["factor"]))
+ "px";
elm.appendChild(a);
elm.appendChild(document.createTextNode(" "));
}
append(elm);
}
function append(e)
{
innerElm.appendChild(e);
}
function getFactor(tags)
{// fixme!!!
var a = new Array();
for (var tag in tags) {
a.push(tags[tag]);
}
a.sort();
var min = Math.log(a[0]);
var max = Math.log(a[a.length-1]);
var factor;
if (max - min) {
factor = 24 / (max - min);
} else {
min -= 24;
factor = 1;
}
if (a.length < 24) {
factor *= a.length / 24;
}
return {"factor": factor, "min": min, "max": max};
}
})();