// ==UserScript==
// @name           hbPop.user.js
// @namespace      http://furyu.tea-nifty.com/
// @description    HatenaBookmark::Pop ver.0.01f
// @include        http://*
// ==/UserScript==

if (typeof unsafeWindow!='undefined') {
	var	__orgWindow__=window;
	window=unsafeWindow;
	document=window.document;
}
(function(){
try {if (window!=top||(window.opener&&window.opener.location.href==window.location.href)) return}catch(e){};
var	w=window,d=document;

// === Options
var	hbFontPixelMin=24;
var	hbFontPixelMax=48;
var	hbStrLengthMax=100;
var	hbOffsetX=84,hbOffsetY=64;
var	hbTimeMax=4,hbTimeSlice=100;
var	hbFontFamily='"MS PGothic", "Hiragino Kaku Gothic Pro", Osaka, sans-serif';
var	hbColors=[
	'white'
,	'cyan'
,	'lime'
,	'yellow'
,	'orange'
,	'pink'
];
var	hbImageIcon=true;
var	hbShowId=true;
var	hbFilterOpacity=75;
var	hbFilterColor='black';
var	hbRetry=3;

// ===
var	setTimeout,clearTimeout,setInterval,clearInterval;
(function(){
var	resolution=10;

var	origSetTimeout=w.setTimeout;
var	origClearTimeout=w.clearTimeout;
var	origSetInterval=w.setInterval;
var	origClearInterval=w.clearInterval;

var	comId=undefined,numId=0,cntId=0,timerInfos=[];
var	fncTout=function(){
	var now=(new Date()).getTime();
	for (var tid in timerInfos) {
		var	timerInfo=timerInfos[tid],handler=timerInfo.handler;
		if (handler&&timerInfo.tout<=now) {
			handler();
			if (timerInfo.resetflg) timerInfo.tout+=timerInfo.tval;
			else delete timerInfos[tid];
		}
	}
};
setTimeout=function(handler,tval,resetflg) {
	var now=(new Date()).getTime();
	if (typeof handler=='string') handler=new Function(handler);
	var	tid='s'+(numId++);
	if (!cntId++) comId=origSetInterval(fncTout,resolution);
	timerInfos[tid]={handler:handler,tval:tval,tout:now+tval,resetflg:resetflg};
	return tid;
};
clearTimeout=function(tid) {
	if (timerInfos[tid]) {
		if (!--cntId) {
			origClearInterval(comId);
			comId=undefined;
		}
		delete timerInfos[tid];
		return undefined;
	}
	else {
		return origClearTimeout(tid);
	}
};
setInterval=function(handler,tval){return setTimeout(handler,tval,true)};
clearInterval=clearTimeout;
})();

var	stripTags=function(txt){return txt.replace(/<\/?[^>]+>/gi,'')};

var	getClientWidth=(function(){
	if (typeof w.innerWidth!='undefined') {
		return function() {return w.innerWidth};
	}
	else if (d.all) {
		if (d.compatMode=='CSS1Compat') {
			return function() {return d.documentElement.clientWidth};
		}
		else {
			return function() {return d.body.clientWidth};
		}
	}
	else {
		return function() {return 0};
	}
})();	//	end of getClientWidth()

var	getClientHeight=(function(){
	if (typeof w.innerHeight!='undefined') {
		return function() {return w.innerHeight};
	}
	else if (d.all) {
		if (d.compatMode=='CSS1Compat') {
			return function() {return d.documentElement.clientHeight};
		}
		else {
			return function() {return d.body.clientHeight};
		}
	}
	else {
		return function() {return 0};
	}
})();	//	end of getClientHeight()

var	getClientTop=(function(){
	if ( typeof w.pageYOffset != 'undefined' ) {
		return function() {return w.pageYOffset};
	}
	else if (d.all) {
		if (d.compatMode=='CSS1Compat') {
			return function() {return d.documentElement.scrollTop};
		}
		else {
			return function() {return d.body.scrollTop};
		}
	}
	else {
		return function() {return 0};
	}
})();	//	end of getClientTop()

//	===
var	getClientLeft=(function(){
	if ( typeof w.pageXOffset != 'undefined' ) {
		return function() {return w.pageXOffset};
	}
	else if (d.all) {
		if (d.compatMode=='CSS1Compat') {
			return function() {return d.documentElement.scrollLeft};
		}
		else {
			return function() {return d.body.scrollLeft};
		}
	}
	else {
		return function() {return 0};
	}
})();	//	end of getClientLeft()

var	setEventHandler=(function(){
	var	handlerList=[],firstcall=true,completed=false;
	var	execFunctions=function(){
		for (var ci=0,len=handlerList.length; ci<len; ci++) handlerList[ci]();
		handlerList=[];
		completed=true;
	};
	if (w.attachEvent && w.navigator.userAgent.match(/msie/i)) {
		var	setHandler=function(obj,evt,handler){
			if (evt=='load'&&obj==w) {
				if (completed||d.readyState=='complete') {
					handler();
				}
				else {
					handlerList[handlerList.length]=handler;
					if (firstcall) {
						d.write('<script type="text/javascript" defer src="javascript:void(0)"><\/script>');
						var	scripts=d.getElementsByTagName('script'),script=scripts[scripts.length-1];
						script.onreadystatechange=function(){
							if (script.readyState=='complete') execFunctions();
						};
						firstcall=false;
					}
				}
			}
			else {
				obj.attachEvent('on'+evt,handler)
			}
		};
		setHandler(w,'load',function(){});
		return setHandler;
	}
	else if (w.addEventListener) {
		if (w.navigator.userAgent.indexOf('AppleWebKit/') > -1) {
			return function(obj,evt,handler){
				if (evt=='load'&&obj==w) {
					var	stat=d.readyState;
					if (completed||stat=='loaded'||stat=='complete') {
						handler();
					}
					else {
						handlerList[handlerList.length]=handler;
						if (firstcall) {
							(function(){
								var	stat=d.readyState;
								if (stat=='loaded'||stat=='complete') execFunctions(); else setTimeout(arguments.callee,50);
							})();
							firstcall=false;
						}
					}
				}
				else {
					obj.addEventListener(evt,handler,false)
				}
			}
		}
		else {
			return function(obj,evt,handler){
				if (evt=='load'&&obj==w) {
					try {d.addEventListener("DOMContentLoaded",handler,false)} catch(e){obj.addEventListener(evt,handler,false)}
				}
				else {
					obj.addEventListener(evt,handler,false);
				}
			};
		}
	}
	else {
		return function(obj,evt,handler){var org=obj['on'+evt];obj['on'+evt]=function(){if(typeof org=='function')org();handler()}};
	}
})();	//	end of setEventHandler()

var	getFontPixel=function(textLen){
	var	fontPixel=hbFontPixelMin;
	if (hbFontPixelMin<hbFontPixelMax) {
		var	fontColorNum=0,chkLen=0;
		var	lenStep=~~(hbStrLengthMax/(hbFontPixelMax-hbFontPixelMin))*4;
		for (fontPixel=hbFontPixelMax;hbFontPixelMin<fontPixel;fontPixel-=4,chkLen+=lenStep,fontColorNum++) {
			if (textLen<chkLen+lenStep) break;
		}
	}
	return fontPixel;
};

var	objectResume,objectSuspend;
(function(){
	var	tgts={
		selects	:	d.getElementsByTagName('select')
	,	objects	:	d.getElementsByTagName('object')
	,	iframes	:	d.getElementsByTagName('iframe')
	};
	for (var mem in tgts) {
		var	tgt=tgts[mem];
		for (var ci=0,len=tgt.length; ci<len; ci++) {
			try{tgt[ci].ovisibility=tgt[ci].style.visibility;}catch(e){};
		}
	}
	objectResume=function(){
		for (var mem in tgts) {
			var	tgt=tgts[mem];
			for (var ci=0,len=tgt.length; ci<len; ci++) {
				try{tgt[ci].style.visibility=tgt[ci].ovisibility;}catch(e){};
			}
		}
	};	//	end of objectResume()
	objectSuspend=function(){
		for (var mem in tgts) {
			var	tgt=tgts[mem];
			for (var ci=0,len=tgt.length; ci<len; ci++) {
				try{tgt[ci].style.visibility='hidden';}catch(e){};
			}
		}
	};	//	end of objectSuspend()
})();

var	createHopper=function(entry,hbContainer,filter){
	var	hid=entry.id,text=entry.content,link=entry.link;
	var	textLen=text.length;
	if (!textLen||textLen<=0) return;
	
	var	cWidth=getClientWidth(),cHeight=getClientHeight(),cLeft=getClientLeft(),cTop=getClientTop();
	var	xOff=cWidth-hbOffsetX-1,yOff=cHeight-hbOffsetY-1;
	var	g=8*yOff/(hbTimeMax*hbTimeMax);
	var	maxVx=xOff/hbTimeMax,maxVy=4*yOff/hbTimeMax;
	var	maxWidth=3*xOff/4+xOff/4*Math.random();
	var	initVy=4*maxVy/5+maxVy/5*Math.random(),texp=2*initVy/g,initVx=maxWidth/texp;
	var	maxFontPixel=getFontPixel(textLen);
	var	rate=maxFontPixel/texp,wrate=maxWidth/texp;
	var	x0=cLeft+xOff,y0=cTop+yOff;
	var	tim=0,curX=x0,curY=y0;
	var	lastX=curX,lastY=curY,endY=cTop+cHeight;
	
	var	hopper=d.createElement('div');
	var	style=hopper.style;
	style.textAlign='left';
	style.fontSize='1px';
	style.width='1px';
	style.height='1px';
	style.color=hbColors[~~(hbColors.length*Math.random())];
	style.position='absolute';
	style.background='transparent';
	style.margin=0;
	style.padding=0;
	style.overflow='hidden';
	style.cursor='pointer';
	style.fontFamily=hbFontFamily;
	style.fontWeight='bolder';
	style.lineHeight='140%';
	style.zIndex=1000000;
	
	hopper.unselectable='on'; // IE only
	
	setEventHandler(hopper,'click',function(e){
		if (!e) e=w.event;
		if (e&&e.shiftKey) w.open(entry.link,'_blank');
	});
	setEventHandler(hopper,'mousemove',function(e){
		try {w.getSelection().removeAllRanges()}catch(e){}
		return false;
	});

	style.left=curX+'px';
	style.top=curY+'px';
	
	if (hbImageIcon) {
		var	img=new Image();
		img.src='http://www.hatena.ne.jp/users/'+hid.slice(0,2)+'/'+hid+'/profile.gif';
		img.title=img.alt='id:'+hid;
		img.width=img.height='1';
		img.border='0';
		hopper.appendChild(img);
	}
	if (!hbImageIcon||hbShowId) text='[id:'+hid+']'+text;
	hopper.appendChild(d.createTextNode(text));
	d.body.insertBefore(hopper,d.body.lastChild);
//	d.body.appendChild(hopper);
	
	var	tid=setInterval(function(){
		tim+=hbTimeSlice;
		var	tsec=tim/1000;
		var	curX=~~(x0-initVx*tsec);
		var	curY=~~(y0-initVy*tsec+g*tsec*tsec/2);
		var	fontPixel=~~(rate*tsec)+1,width=~~(wrate*tsec);
		if (maxFontPixel<fontPixel) fontPixel=maxFontPixel;
		style.top=curY+'px';
		style.left=curX+'px';
		style.fontSize=fontPixel+'px';
		style.height=style.width=width+'px';
		if (hbImageIcon) img.width=img.height=fontPixel;
		if (lastY<curY&&endY<=curY) {
			clearInterval(tid);
			style.display='none';
			style.height='auto';
			style.border='orange double 3px';
			style.color='navy';
			style.background='lightyellow';
			style.fontSize=maxFontPixel+'px';
			style.left='4px';
			style.top=(hbContainer.parentNode.style.top.replace(/[^\d]/g,'')-hbFontPixelMax*3)+'px';
			var	imgSmall=new Image();
			imgSmall.src='http://www.hatena.ne.jp/users/'+hid.slice(0,2)+'/'+hid+'/profile_s.gif';
			imgSmall.title=img.alt=text;
			imgSmall.border='0';
			var	ss=imgSmall.style;
			ss.cursor='pointer';
			ss.zIndex='1000000';
			ss.styleFloat=ss.cssFloat='right';
			ss.margin=0;
			ss.padding=0;
			
			setEventHandler(imgSmall,'click',function(e){
				w.open(entry.link,'_blank');
			});
			setEventHandler(imgSmall,'click',function(e){
				w.open(entry.link,'_blank');
			});
			setEventHandler(imgSmall,'mouseover',function(e){
//				style.top=(hbContainer.parentNode.style.top.replace(/[^\d]/g,'')-hbFontPixelMax*3)+'px';
				style.top=(getClientTop()+getClientHeight()/2)+'px';
				style.width=(getClientWidth()-24)+'px';
				style.display='block';
			});
			setEventHandler(imgSmall,'mouseout',function(e){
				style.display='none';
			});
			hbContainer.appendChild(imgSmall);
			return;
		}
		lastY=curX; lastY=curY;
	},hbTimeSlice);
};

var	createHbox=function(cmtEntries,hbURL,errorInfo){
	var	hbar=d.createElement('div');
	var	style=hbar.style;
	style.background='transparent';
	style.position='absolute';
	style.left=0;
	style.margin=0;
	style.padding=0;
	style.zIndex=1000000;
	
	var	hbContainer=d.createElement('div');
	var	style=hbContainer.style;
	style.margin=0;
	style.padding='4px 0px';
	style.textAlign='left';
	style.styleFloat=style.cssFloat='left';
	
	var	hbox=d.createElement('div');
	var	style=hbox.style;
	style.margin=0;
	style.padding=0;
	style.width='82px';
	style.height='40px';
	style.overflow='hidden';
//	style.border='ridge 8px navy';
	style.border='solid 2px navy';
	style.background='#1841CE url("http://b.hatena.ne.jp/images/hatenade.gif") center no-repeat';
	style.cursor='pointer';
	style.styleFloat=style.cssFloat='right';
	style.textAlign='left';
	hbox.unselectable='on'; // IE only
	
	var	hcounter=d.createElement('div');
	var	style=hcounter.style;
	style.margin=0;
	style.padding='4px';
	style.color='lime';
	style.fontSize='16px';
	style.fontWeight='bolder';
	style.fontFamily=hbFontFamily;
	style.background='transparent';
	style.textAlign='left';
	hcounter.unselectable='on'; // IE only

	var	updateNumber=function(number){
		if (isNaN(number)) {
			hcounter.style.color='red';
			numStr=number;
		}
		else {
			while (hcounter.firstChild) hcounter.removeChild(hcounter.firstChild);
			var	numStr=number.toString();
			if (numStr.length<3) numStr=(1000+number).toString().replace(/^./,'');
		}
		hcounter.appendChild(d.createTextNode(numStr));
	};
	if (cmtEntries) {
		updateNumber(cmtEntries.length);
	}
	else {
		updateNumber('Error');
		hbox.title=errorInfo;
	}
	hbox.appendChild(hcounter);
	
	hbar.appendChild(hbContainer);
	hbar.appendChild(hbox);
	
	d.body.insertBefore(hbar,d.body.lastChild);
//	d.body.appendChild(hbar);
	
	var	filter=d.createElement('div');
	var	style=filter.style;
	style.position='absolute';
	style.top=0;
	style.left=0;
	style.background=hbFilterColor;
	style.filter='alpha(opacity='+hbFilterOpacity+')';
	style.MozOpacity=hbFilterOpacity/100;
	style.opacity=hbFilterOpacity/100;
	style.zIndex=999999;
	style.display='none';
	d.body.insertBefore(filter,d.body.lastChild);
//	d.body.appendChild(filter);
	
	if (cmtEntries) {
		setEventHandler(hbox,'click',function(e){
			if (!e) e=w.event;
			if (e&&e.shiftKey) {
				w.open(hbURL,'_blank');
				return;
			}
			if (cmtEntries.length<=0) return;
			new createHopper(cmtEntries.shift(),hbContainer,filter);
			updateNumber(cmtEntries.length);
		});
	}
	setEventHandler(hbox,'mousemove',function(e){
		try {w.getSelection().removeAllRanges()}catch(e){}
		return false;
	});
	setEventHandler(hbar,'mouseover',function(e){
		filter.style.display='block';
		objectSuspend();
	});
	setEventHandler(hbar,'mouseout',function(e){
		filter.style.display='none';
		objectResume();
	});
	var	refreshHbar=function(){
		var	left=getClientLeft(),top=getClientTop(),width=getClientWidth(),height=getClientHeight();
		
		var	s=filter.style;
		s.left=left+'px';
		s.top=top+'px';
		s.width=width+'px';
		s.height=height+'px';
		
		var	s=hbar.style;
		s.width=(width-16)+'px';
		s.top=(top+height-hbOffsetY-1)+'px';
		
		hbContainer.style.width=(width-hbOffsetX-32)+'px';
	};
	setEventHandler(w,'scroll',refreshHbar);
	setEventHandler(w,'resize',refreshHbar);

	refreshHbar();
	
	return hcounter;
};

var	baseURL='http://b.hatena.ne.jp/entry/',baseRSS=baseURL+'rss/',targetURL=w.location.href;

w.hbPopCallback=function(result){
	if (result&&0<result.count) {
		var	entries=result.value.items,cmtEntries=[];
		for (var ci=0,len=entries.length; ci<len; ci++) {
			var	entry=entries[ci], content=stripTags(entry.content);
			if (0<content.replace(/(\s|[\r\n])/mg,'').length) {
				cmtEntries[cmtEntries.length]={
					id		:	entry.title
				,	content	:	content
				,	link	:	entry.link
				};
			}
		}
		if (0<cmtEntries.length) createHbox(cmtEntries,baseURL+targetURL);
	}
};

(function(){
	var	s=d.createElement('script');
	s.type='text/javascript';
	s.src='http://pipes.yahoo.com/furyu/hbcmt?_render=json&_callback=hbPopCallback&_run=1&url='+encodeURIComponent(targetURL);
	d.body.insertBefore(s,d.body.lastChild);
//	d.body.appendChild(s);
})();

})();

