/*
* @title ブクマカのメタブ表示
* @description ブクマカのメタブ表示
* @include http://b.hatena.ne.jp/entry/*
* @license MIT License
* @require
*/
(function(){
/*
* CONSTANTS
*/
var DEBUG = true;
var HBBP_URL = "http://b.hatena.ne.jp/js/bookmark_blogparts.js";
var HATEB_DOMAIN = "http://b.hatena.ne.jp";
var API_DOMAIN = "//b.hatena.ne.jp";
var ICON_DOMAIN = "http://cdn1.www.st-hatena.com/users/";
var CSS = [
'.metab-container {',
' margin: 5px;',
' padding: 5px;',
' border: solid #9CF 1px;',
' border-radius: 10px;',
'}',
'.metab-container > .metab-count{',
' font-size: 10px;',
' font-weight: 900;',
' color: #F00;',
' background-color: #FCC;',
' display: inline-block;',
' text-decoration: none;',
' line-height: 12px;',
' padding: 2px;',
'}',
'.metab-container > ul{',
' display: block;',
' margin: 0px;',
' padding: 0px;',
'}',
'.metab-container > ul.comments > li{',
' width: auto !important;',
' margin: 0px;',
' padding: 0px;',
' display: block;',
' list-style: none;',
'}',
'.metab-container > ul.no-comments > li{',
' width: auto !important;',
' margin: 0px 11px 0px 0px;',
' padding: 0px;',
' border: none;',
' list-style: none;',
' display: inline-block;',
'}',
'.metab-container > ul > li > a.username{',
' display: inline-block;',
' margin: 0px 11px 0px 0px;',
'}',
'.metab-container > ul > li > span.tags{',
' display: inline-block;',
' margin: 0px 11px 0px 0px;',
'}',
'.metab-container > ul > li > span.comment{',
' font-size: 11px;',
'}',
''].join("\n");
//////////////////////////////
var doc = document;
var win = window;
var loc = location;
var con = console;
var p = function p() {
if ( !DEBUG ) return;
con.log.apply(con, arguments);
};
var forEach = function forEach(a,f){
if(!a) return;
for (var i=0,l=a.length;i<l;i++){
if(f(a[i]) === false) break;
}
};
var gensym = (function(){
var rnd = function(){return Math.floor(Math.random() * (1<<30)).toString(16);};
var cnt = 0;
var prefix = 'sym_' + Date.now().toString(16) + '_' + rnd() + '_';
return function gensym(){ return prefix + (cnt++).toString(16); };
})();
var receiver = function(cb){
var name = gensym();
var func = function(){
delete win[name];
cb.apply(this, arguments);
};
win[name] = func;
return encodeURIComponent( name );
};
//////////////////////////////
var users = {};
var htmlifyIcon = function(bm){
var a = doc.createElement('a');
a.href = HATEB_DOMAIN + '/' + bm.user + '/';
a.target = '_blank';
a.title = bm.user;
a.className = 'profile-icon';
var icon = doc.createElement('img');
icon.src =
ICON_DOMAIN + '/' + bm.user.substring(0,2) + '/' + bm.user +
'/profile_l.gif';
icon.alt = bm.user;
a.appendChild(icon);
return a;
};
var htmlifyUsername = function(bm){
var a = doc.createElement('a');
a.href = HATEB_DOMAIN + '/' + bm.user + '/';
a.target = '_blank';
a.title = bm.user;
a.className = 'username';
a.appendChild(doc.createTextNode(bm.user));
return a;
};
var htmlifyTags = function(bm){
var tags = bm.tags || [];
if(tags.length < 1) return doc.createDocumentFragment();
var tagSpan = doc.createElement('span');
tagSpan.className = 'tags';
forEach(tags , function(tagName){
var tagLink = doc.createElement('a');
tagLink.className = 'user-tag';
tagLink.href =
HATEB_DOMAIN + '/' + bm.user + '/' + encodeURIComponent(tagName);
tagLink.appendChild(doc.createTextNode(tagName));
tagSpan.appendChild(tagLink);});
return tagSpan;};
var htmlifyComment = (function(){
var reURL = (function(){
var RE_HEX = '%[a-fA-F0-9][a-fA-F0-9]';
var RE_SCHEME = '[a-z]+:';
var RE_CHAR = '(?:[a-zA-Z0-9\-_\.]|' + RE_HEX + ')';
var RE_STR = RE_CHAR + '+';
var RE_STR0 = RE_CHAR + '*';
var RE_HOST = RE_STR;
var RE_PATH = '(?:/(?:' + RE_STR + '/)*' + RE_STR0 + ')';
var RE_QV = RE_STR0 + '=' + RE_STR0;
var RE_QUERY = '(?:\\?(?:(?:' + RE_QV + '&)*'+RE_QV+')?|'+RE_QV+')';
var RE_HASH = '(?:#' + RE_STR0 + ')';
var RE_URL = 'https?://' + RE_HOST + RE_PATH +'?' +
RE_QUERY + '?' + RE_HASH + '?';
return new RegExp('(.*?)(' + RE_URL + ')(.*)');
})();
return function(bm){
var comment = bm.comment;
var R = doc.createElement('span');
R.className = 'comment';
while(comment.length > 0){
var match = comment.match(reURL);
if(!match){
if(comment.length > 0) R.appendChild(doc.createTextNode(comment));
break;
}
var head = match[1];
var url = match[2];
comment = match[3];
if(head.length > 0) R.appendChild(doc.createTextNode(head));
var a = doc.createElement('a');
a.href = url;
a.target = '_blank';
a.appendChild(doc.createTextNode(url));
R.appendChild(a);
}
return R;
};})();
var htmlifyMeta = function(bm, entry){
var meta = doc.createElement('div');
meta.className = 'user-comment-meta';
var plink = doc.createElement('a');
plink.className = 'user-comment-link';
plink.href = '/entry/' + entry.eid + '/comment/' + bm.user;
plink.title = 'パーマリンク';
plink.target = '_blank';
plink.appendChild(doc.createTextNode('リンク'));
meta.appendChild(plink);
var tspan = doc.createElement('span');
tspan.className = 'timestamp';
tspan.appendChild(doc.createTextNode(bm.timestamp));
meta.appendChild(tspan);
var star = doc.createElement('span');
star.className = 'hatena-bookmark-star';
meta.appendChild(star);
return meta;
};
var toHTML = function(entry, user){
var slot = users[user];
var node = slot.html || null;
if(!node){
node = doc.createElement('div');
if(entry){
node.className = 'metab-container';
var count = doc.createElement('a');
count.className = 'metab-count';
count.href = entry.entry_url;
count.target = "_blank";
count.appendChild(doc.createTextNode(String(entry.count) + " users"));
node.appendChild(count);
if((entry.bookmarks || []).length > 0){
var comments = doc.createElement('ul');
comments.className = 'comments';
var noComments = doc.createElement('ul');
noComments.className = 'no-comments';
forEach(entry.bookmarks, function(bm){
var li = doc.createElement('li');
li.appendChild(htmlifyIcon( bm));
li.appendChild(htmlifyUsername(bm));
li.appendChild(htmlifyTags( bm));
li.appendChild(htmlifyComment( bm));
li.appendChild(htmlifyMeta( bm, entry));
(String(bm.comment).length > 0 // || tags.length > 0
? comments : noComments).appendChild(li);});
if(comments.firstChild) node.appendChild(comments);
if(noComments.firstChild) node.appendChild(noComments);}}
slot.html = node;}
var retval = node.cloneNode(true);
return retval;
};
var received = function(user, entry){
var slot = users[user];
slot.entry = entry || false;
slot.cont.forEach(function(c){c(entry, user);});
};
var reserve = function(user, cont){
p(user);
var slot = ( users[user] || (users[user] = {entry: null,cont:[],req: false} ));
if(slot.entry !== null){
cont(slot.entry, user);
return;
}
slot.cont.push(cont || function(){});
if(slot.req) return;
slot.req = true;
var uri = HATEB_DOMAIN + '/' + user + '/';
var apiEndPoint = API_DOMAIN + '/entry/jsonlite/?';
var request = apiEndPoint + 'url=' + encodeURIComponent(uri) +
'&callback=' + receiver(function(entry){ received(user, entry);});
var scriptTag = doc.createElement('script');
scriptTag.src = request;
scriptTag.type = 'text/javascript';
doc.body.appendChild(scriptTag);
};
var main = function(){
var entries = [];
var style = doc.createElement('style');
style.type = 'text/css';
style.appendChild(doc.createTextNode(CSS));
doc.querySelector('head').appendChild(style);
forEach(doc.querySelectorAll('a.profile-icon'), function(n){
var user = n.href.match(/([^\/]+)\/$/)[1];
reserve(user, function(entry, user){
n.parentNode.appendChild(toHTML(entry, user));});});};
////
if((function(pn){
if(pn.match(/^\/entry\/\d+\/comment\//)) return true;
return false;
})(String(loc.pathname))) return;
main();
})();
/*/
hoge:(
{"count":2,
"bookmarks":[
{"timestamp":"2016/06/24 18:41:59",
"comment":"","user":"aflat_1000dai4","tags":["meta bookmark"]},
{"timestamp":"2014/11/27 23:31:08",
"comment":"","user":"kcolmun",
"tags":["\u30e1\u30bf\u30d6\u30c3\u30af\u30de\u30fc\u30af"]}],
"url":"http://b.hatena.ne.jp/guru_guru/",
"eid":234900219,
"title":"\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af - guru_guru \u306e\u30d6\u30c3\u30af\u30de\u30fc\u30af",
"screenshot":"http://screenshot.hatena.ne.jp/images/200x150/7/7/5/1/8/4cdd713947a7e5c74bf0b8244024e6ea7ae.jpg",
"entry_url":"http://b.hatena.ne.jp/entry/b.hatena.ne.jp/guru_guru/"}
)
//*/
//*///
// Local Variables:
// mode: hatena-let
// End: