// ==UserScript==
// @name           readmore.user.js
// @namespace      http://furyu.tea-nifty.com/
// @description    ReadMore ver.0.03d (SeaHorse/Greasemonkey)
// @include        http://*
// @type           SleipnirScript
// ==/UserScript==
//
// author: furyu (http://furyu.tea-nifty.com/annex/)
// script: http://furyu.tea-nifty.com/script/readmore.user.js
//
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html

(function(){

var	readmore=function(win){

// === Parameters
var	regAnames=new RegExp('(more)','i');

var	forceCheckAtext=false;	//	true: checkAtextUrlsの設定を無視して全サイトで試行(テスト用)
var	checkAtextUrls=[
/*
■「続きを読む」リンクのhrefにアンカー指定が無いサイトを登録
	以下の条件に該当するサイトならば表示できる可能性有り。
	・ リンク文字列がregAtextsの正規表現にマッチ。
	・ 飛び先のページ上はアンカー(#more)が存在。
	※ 上記以外でも、運がよければあるいは……(笑)。
*/
	/^http:\/\/.*?\.fc2\.com\//
,	/^http:\/\/.*?\.livedoor\..*?\//
,	/^http:\/\/.*?\.shinobi\.jp\//
,	/^http:\/\/.*?\.[^.\/]+-nifty\.com\//
];
var	regAtexts=new RegExp('\x28\u7d9a\x28\u304d\x7c\u304f\x29\x7c\u3064\u3065\x28\u304d\x7c\u304f\x29\x7c\u7701\u7565\x7c\u5168\u3066\x7c\u3059\u3079\u3066\x7c\u4ee5\u4e0b\x7cmore\x29','i');
//	(続(き|く)|つづ(き|く)|省略|全て|すべて|以下|more)

var	minMatchLength=5;	//	続きを認識するための元の文の基準値(※元ページと読込先ページでminMatchLength文字以上一致すればそこを続きを見なす)

var	sameDomainOnly=true;

var	marginTop=24;


// === Preparation
var	w=(win)?win:window,d=w.document;
var	sleipnir=w.sleipnir;

if (w._readmore_user_js) return;
w._readmore_user_js=true;

var	log=(function(){
	if (sleipnir) {
		return function(msg){sleipnir.Output.Print(msg)}
	}
	else if (typeof console!='undefined') {
		return function(msg){console.log(msg)};
	}
	else if (typeof GM_log!='undefined') {
		return function(msg){GM_log(msg)};
	}
	else {
		return function(msg){prompt('ReadMore',msg)};
	}
	w.focus();
})();

try {
	var	frames=d.getElementsByTagName('frame');
}
catch(e) {
	return;
}
if (0<frames.length) {
	for (var ci=0,len=frames.length; ci<len; ci++) {
		try {
			var	cwin=frames[ci].contentWindow;
			cwin.sleipnir=sleipnir;
			arguments.callee(cwin);
			cwin.sleipnir=null;
		}
		catch (e) {};
	}
	return;
}

// === Common Functions
var	setEventHandler=(function(){
	if (w.addEventListener) {
		return function(obj,evt,handler){
			if (evt=='load'&&obj==w) {
				try {d.addEventListener("DOMContentLoaded",handler,false)} catch(e){obj.addEventListener(evt,handler,false)}
			}
			else {
				if (evt=='mousewheel'&&w.navigator.userAgent.match(/Firefox/i)) evt='DOMMouseScroll';
				obj.addEventListener(evt,handler,false);
			}
		};
	}
	else if (w.attachEvent) {
		return function(obj,evt,handler){obj.attachEvent('on'+evt,handler)};
	}
	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	getObjectTop=(function(){
	if (sleipnir) {
		return	function(obj){
			var	style=obj.currentStyle;
			var	pos=obj.getBoundingClientRect();
			var	oTop=pos.top;
			if (d.compatMode=='CSS1Compat') {
				oTop+=d.documentElement.scrollTop-d.documentElement.clientTop;
			}
			else {
				var	bstyle=d.body.currentStyle;
				oTop+=d.body.scrollTop-(parseInt(bstyle.borderTopWidth)||0);
			}
			return oTop;
		};
	}
	else {
		return	function(obj){
			var	chkflg=false;
			try {
				var style=obj.currentStyle||d.defaultView.getComputedStyle(obj,'');
				if (style.display=='none') {
					var	bkdisplay=obj.style.display;
					obj.style.display='block';
					chkflg=true;
				}
			} catch(e){}
			var offsetTop=0,curObj=obj;
			try {
				while (curObj) {
					var	style=curObj.currentStyle||d.defaultView.getComputedStyle(curObj,'');
					offsetTop+=curObj.offsetTop+(parseInt(style.borderTopWidth)||0);
					curObj=curObj.offsetParent;
				}
			} catch(e){}
			if (chkflg) obj.style.display=bkdisplay;
			return offsetTop;
		};
	}
})();	//	end of getObjectTop()

var	scrollIntoView=function(obj){
//	obj.scrollIntoView(true);
	w.scrollTo(Math.max(d.documentElement.scrollLeft,d.body.scrollLeft),getObjectTop(obj)+obj.offsetHeight-marginTop);
};	//	end of scrollIntoView()

var	pathToUrl=(function(){
	var wimg=new Image();
	var	spathToUrl=function(path,base){
		wimg.src=path;
		return wimg.src;
	}
	return spathToUrl;
})();

var	isSameDomain=function(url){
	return (pathToUrl(url).match(new RegExp('^http?:\/\/'+w.location.host)))?true:false;
};

var	getXmlHttpObj=(function(){
	return function(){return sleipnir.CreateObject('Msxml2.XMLHTTP')};
})();	//	end of getXmlHttpObj()

var	getPageRequest=(function(){
	if (sleipnir) {
		return function(path,callback,referer){
			var	ret=false;
			for (;;) {
				if (!path) break;
				var	xh=getXmlHttpObj();
				if (!xh) break;
				var	async=false;
				if (typeof callback=='function') {
					xh.onreadystatechange = function() {
						for (;;) {
							if (xh.readyState!=4) break;
							callback((xh.status==200)?xh:'',path,referer);
							break ;
						}
					};
					async=true;
				}
				xh.open('GET',path,async) ;
				xh.setRequestHeader('User-agent','Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
				xh.setRequestHeader('Content-Type',"text/plane; charset="+d.charset);
				if (isSameDomain(path)) {
					if (d.cookie!='') xh.setRequestHeader('Cookie',d.cookie);
				}
				xh.setRequestHeader('Referer:',(referer)?referer:w.location.href);
				xh.send('') ;
				ret=(async)?true:xh;
				break ;
			}
			return ret ;
		};
	}
	else {
		return function(path,callback,referer){
			GM_xmlhttpRequest({
					method				:	'get'
				,	url					:	path
				,	overrideMimeType	:	'text/html; charset='+d.characterSet
				,	onload				:	function(xh){callback(xh,path,referer);}
				,	onerror				:	function(){callback('',path,referer);}
			});
		};
	}
})();	//	end of getPageRequest()

var	getHtmlDocument=(function(){
	if (sleipnir) {
		return function(xh){
			var	hdoc=null;
			for (;;) {
				if (!xh) break;
				try {
					var	rspText='';
					if (d.charset.match(/utf-8/i)) {
						rspText=xh.responseText;
					}
					else {
						var	adstrm=sleipnir.CreateObject('ADODB.Stream');	//	NG: new ActiveXObject('ADODB.Stream')
						adstrm.Type=1;	// binary
						adstrm.Open();
						adstrm.Write(xh.responseBody);
						adstrm.Position=0;
						adstrm.Type=2;	//	text
						adstrm.Charset=d.charset;
						rspText=adstrm.ReadText();
						adstrm.Close();
						adstrm=null;
					}
					var	hdoc=new ActiveXObject('htmlfile');
					hdoc.designMode='on';
					hdoc.open('text/html');
					hdoc.write(rspText);
					hdoc.close();
				} catch(e) {}
				break;
			}
			return hdoc;
		};
	}
	else {
		if (d.implementation&&d.implementation.createHTMLDocument) {
			var	hdoc=d.implementation.createHTMLDocument('');
		}
		else {
			var proc=new XSLTProcessor();
			var xsltStyleSheet=new DOMParser().parseFromString([
				'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">'
			,		'<xsl:output method="html" />'
			,		'<xsl:template match="/">'
			,			'<html><head><title></title></head><body></body></html>'
			,		'</xsl:template>'
			,	'</xsl:stylesheet>'
			].join(''),'application/xml');
			proc.importStylesheet(xsltStyleSheet);
			var	hdoc=proc.transformToDocument(xsltStyleSheet);
		}
		var range=hdoc.createRange(); // rangeまでは予め用意しておけば、GETの度に作成する必要はない
		
		return function(xh){
			//var	hdoc=null;
			for (;;) {
				if (!xh) break;
				/*
				//try {
				//	var	hdoc=d.implementation.createDocument(null,'html',null);
				//	var htmlsrc=xh.responseText.replace(/[\s\S]*?<html[\s\S]*?>/i,'').replace(/<\/html>/i,'');
				//	var range=d.createRange();
				//	range.setStartAfter(d.body);
				//	var	frgm=range.createContextualFragment(htmlsrc);
				//	try {
				//		frgm=hdoc.adoptNode(frgm);
				//	}
				//	catch(e) {
				//		frgm=hdoc.importNode(frgm,true);
				//	}
				//	hdoc.documentElement.appendChild(frgm);
				//} catch(e) {}
				*/
				var	html=xh.responseText;
				html=html.match(/<html[^>]*>([\s\S]*)<\/html/i)[1];
				range.selectNodeContents(hdoc.documentElement);
				range.deleteContents();
				hdoc.documentElement.appendChild(range.createContextualFragment(html));
				break;
			}
			return hdoc;
		};
	}
})();	//	end of getHtmlDocument()

var	cancelBubble=function(e){
	if (!e) e=w.event;
	if (!e) return;
	if (e.stopPropagation) {
		e.preventDefault();
		e.stopPropagation();
	}
	else {
		e.returnValue=false;
		e.cancelBubble=true;
	};
	return false;
};	//	end of cancelBubble()

var	isWheelDown=function(e){
	if (!e) e=w.event;
	if (!e) return false;
	var	delta=0;
	if (e.wheelDelta) {
		delta=e.wheelDelta/120;
//		if (w.opera) delta=-delta;
	}
	else if (e.detail) {
		delta=-e.detail/3;
	}
	return ((delta<0)?true:false);
};	//	end of isWheelDown()

var	xpathGetElements=function(xpath,base){
	var	hNodes=[];
	if (!base) base=d;
	try {
		var nsnaps=base.evaluate(xpath,base,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
		for (var ci=0,len=nsnaps.snapshotLength; ci<len; ci++) {
			hNodes[ci]=nsnaps.snapshotItem(ci);
		}
	} catch(e){}
	return hNodes;
};	//	end of xpathGetElements()

var	xpathGet1stElement=function(xpath,base){
	if (!base) base=d;
	try {
		return base.evaluate(xpath,base,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;
	}
	catch(e){
		return null;
	}
};	//	end of xpathGet1stElement()

var	getElementsByTagAndClassName=(function(){
	var	splitClassName=function(className){
		return className.replace(/\s+/g,' ').replace(/(^\s|\s$)/g,'').split(' ');
	};
	if (sleipnir) {
		return function(tagName,className,doc) {
			if (!doc) doc=d;
			var children=doc.getElementsByTagName(tagName);
			if (className) {
				var	chkElms=splitClassName(className);
				var	flgElms=[];
				for (var ci=0,len=chkElms.length; ci<len; ci++) flgElms[chkElms[ci]]=true;
				var elements=[];
				for (var ci=0,leni=children.length; ci<leni; ci++) {
					var child=children[ci];
					var cname=child.className;
					if (!cname) continue;
					var cnameElms=splitClassName(cname);
					for (var cj=0,lenj=cnameElms.length; cj<lenj; cj++) {
						if (flgElms[cnameElms[cj]]) {
							elements[elements.length]=child;
							break;
						}
					}
				}
				return elements;
			}
			else {
				return children;
			}
		};
	}
	else {
		return function(tagName,className,doc) {
			if (!doc) doc=d;
			tagName=tagName.toLowerCase();
			if (className) {
				var	chkElms=splitClassName(className);
				var	xps=[];
				for (var ci=0,len=chkElms.length; ci<len; ci++) {
					xps[xps.length]='//'+tagName+'[@class="'+chkElms[ci]+'"]';
				}
				return xpathGetElements(xps.join('|'),doc);
			}
			else {
				return xpathGetElements('//'+tagName,doc);
			}
		};
	}
})();	//	end of getElementsByTagAndClassName()

var	getAnchorByName=(function(){
	if (sleipnir) {
		return function(name,doc) {
			if (!name) return null;
			if (!doc) doc=d;
			if (typeof name=='string') {
				var	elm=doc.getElementById(name);
				if (elm) return elm;
				var	tElms=(doc.anchors)?doc.anchors:doc.getElementsByTagName('a');
				for (var ci=0,len=tElms.length; ci<len; ci++) {
					if (tElms[ci].name==name) return tElms[ci];
				}
			}
			else if (name.constructor==RegExp) {
				var	tElms=(doc.anchors)?doc.anchors:doc.getElementsByTagName('a');
				for (var ci=0,len=tElms.length; ci<len; ci++) {
					var	tElm=tElms[ci];
					if ((tElm.id&&tElm.id.match(name))||(tElm.name&&tElm.name.match(name))) return tElm;
				}
			}
			return null;
		};
	}
	else {
		return function(name,doc) {
			if (!name) return null;
			if (!doc) doc=d;
			if (typeof name=='string') {
				return xpathGet1stElement('id("'+name+'")|//a[@'+'name="'+name+'"]',doc);
			}
			else if (name.constructor=='RegExp') {
				var	tElm=xpathGetElements('//a[@id!=""]|//a[@'+'name!=""]',doc);
				for (var ci=0,len=tElms.length; ci<len; ci++) {
					var	tElm=tElms[ci];
					if ((tElm.id&&tElm.id.match(name))||(tElm.name&&tElm.name.match(name))) return tElm;
				}
			}
			return null;
		};
	}
})();	//	end of getAnchorByName()

var	createRange=(function(){
	if (sleipnir) {
		return function(doc){return doc.body.createTextRange()};
	}
	else {
		return function(doc){return doc.createRange()};
	}
})();	//	end of createRange()

var	getNodeText=(function(){
	if (sleipnir) {
		return function(node,rng){
			rng.moveToElementText(node);
			return rng.text.replace(/\r\n/g,'\n');
				/*	【IEの不具合対策】
					そのままだとTextRange.text.lengthの値とTextRange.moveEnd('character', N)などで指定する値の整合がとれない。
					・TextRangeでは<br />などは改行文字と解釈されて、TextRange.textに含まれる。
					・TextRange.text.lengthの値には、改行を2文字(<CR><LF>)として計算した値が入る。
					・TextRange.text.lengthの値には、最後の文字(改行以外)から後の改行文字数は含まれない。
					・TextRange.moveEnd('character', N)で選択範囲を移動する際には、Nには改行を1文字とみなした数値を指定する必要がある。
					このため、<CR><LF>→<LF>変換を実施。
				*/
		};
	}
	else {
		return function(node,rng){
			rng.selectNodeContents(node);
			return rng.toString();
		};
	}
})();	//	end of getRangeText()

var	truncNode=(function(){
	if (sleipnir) {
		return function(node,tlen,rng) {
			rng.moveToElementText(node);
//			log('before trunc:'+rng.text.length);
//			rng.moveEnd('character',tlen-tgtTrng.text.length);	// NG
			rng.collapse(true);	//	rng.setEndPoint('EndToStart',rng);
			rng.moveEnd('character',tlen);
			rng.execCommand("delete");
//			rng.moveToElementText(node);
//			log('after trunc:'+rng.text.length);
		};
	}
	else {
		return function(node,tlen,rng) {
			if (tlen<=0) return tlen;
			var	cnode=node.firstChild;
			while (cnode) {
				var	nnode=cnode.nextSibling;
				switch (cnode.nodeType) {
					case	1	:
					case	9	:
						tlen=arguments.callee(cnode,tlen);
						break;
					case	3	:
						var	text=cnode.nodeValue;
						if (text.length<tlen) {
							tlen-=text.length;
						}
						else {
							cnode.nodeValue=text.substring(tlen,text.length);
							tlen=0;
						}
						break;
					defaulut	:
						break;
				}
				if (0<tlen) {
					node.removeChild(cnode);
				}
				else {
					break;
				}
				cnode=nnode;
			}
			return tlen;
		};
	}
})();	//	end of truncNode()


// === Global Variables
var	nowload=new Image();
nowload.border=0;
nowload.src='http://furyu-tei.sakura.ne.jp/icon/nowloading1.gif';
var	sMark=d.createElement('div');
with (sMark.style) {cursor='pointer';fontFamily='verdana'; fontSize='10px'; fontWeight='bolder'; display='block'; color='darkblue'; backgroundColor='lightyellow';}
var	eMark=sMark.cloneNode(true);
sMark.title='[ReadMore] wheel-down="to bottom" click="close"';
eMark.title='[ReadMore] wheel-up="to top" click="close"';
sMark.innerHTML='v[*';
eMark.innerHTML='^[*';

var	linkCount=0;
var	readMoreObjs=[];
var	curlocation=w.location.href;


// === Constructor and Prototype Definitions
var	ReadMoreObject=function(link,url,aname){
	var	self=this;
	
	self.ready=false;
	
	readMoreObjs[linkCount]=self;
	linkCount++;
	link.setAttribute('_readmore_switch_no_',linkCount);
	
	self.number=linkCount;

	self.link=link;
	self.url=url;
	self.aname=aname;
	self.workDiv=d.createElement('div');
	
	self.load(url);
};	//	end of ReadMoreObject() [constructor]

ReadMoreObject.prototype.load=function(url){
	var	self=this;
	self.nowload=nowload.cloneNode(true);
	self.link.appendChild(self.nowload);
	getPageRequest(url,function(xh){self.callback(xh)});
};	//	end of ReadMoreObject.prototype.load()

ReadMoreObject.prototype.srcTrng=createRange(d);

ReadMoreObject.prototype.callback=function(xh){
	var	self=this;
	
	var	link=self.link;
	var	url=self.url;
	var	aname=self.aname;
	var	workDiv=self.workDiv;
	var	number=self.number;
	
	link.removeChild(self.nowload);
	self.nowload=null;
	
	var	hdoc=self.hdoc=getHtmlDocument(xh);
	if (!hdoc) return;
	//var	mstart=getAnchorByName((aname)?aname:regAnames,hdoc);
	var	mstart=getAnchorByName(aname,hdoc);
	if (!mstart) {
		var	maxlen=0;
		var	baseNode=link.parentNode;
		var	srcTrng=self.srcTrng;
		var	tgtTrng=createRange(hdoc);
		var	pNode=null;
		var	flg_trunc=true;
		var	cmp_st=function(srcText,tgtText){
			//log('src:'+srcText);
			//log('tgt:'+tgtText);
			var	sum=0,txtlen=(srcText.length<tgtText.length)?srcText.length:tgtText.length;
			for (; sum<txtlen; sum++) {
				if (srcText.charAt(sum)!=tgtText.charAt(sum)) break;
			}
			if (maxlen<=sum) {
				maxlen=sum;
//				log('<'+checkNode.tagName+' class="'+baseNode.className+'">:length='+maxlen);
				pNode=checkNode;
			}
		};
		while (baseNode) {
			if (baseNode.nodeType!=1) break;
			if (!baseNode.className) {
				baseNode=baseNode.parentNode;
				continue;
			}
			var	checkNodes=getElementsByTagAndClassName(baseNode.tagName,baseNode.className,hdoc);
			for (var ci=0,len=checkNodes.length; ci<len; ci++) {
				var	checkNode=checkNodes[ci];
				srcText=getNodeText(baseNode,srcTrng);
				tgtText=getNodeText(checkNode,tgtTrng);
				flg_trunc=true;
				cmp_st(srcText,tgtText);
				if (minMatchLength<=maxlen) break;
				flg_trunc=false;
				cmp_st(srcText.replace(/\s/g,''),tgtText.replace(/\s/g,''));
			}
			if (minMatchLength<=maxlen) break;
			baseNode=baseNode.parentNode;
		}
		if (!pNode) return;
		if (flg_trunc) truncNode(pNode,maxlen,tgtTrng);
		mstart=pNode.firstChild;
	}
	var	pNode=mstart.parentNode,tmpElm,baseNode=link.parentNode,imark=link;
	var	className=pNode.className;
	if (className) {
		var	tmpElm=baseNode,tmpParent;
		while (tmpElm) {
			tmpParent=tmpElm.parentNode;
			if (tmpParent&&tmpParent.className==className) {
				imark=tmpElm;
				baseNode=tmpParent;
				break;
			}
			tmpElm=tmpParent;
		}
	}
	while (tmpElm=pNode.firstChild) {
		if (tmpElm==mstart) break;
		pNode.removeChild(tmpElm);
	}
	if (sleipnir) {
		workDiv.innerHTML=pNode.innerHTML;
	}
	else {
		while (tmpElm) {
			workDiv.appendChild(d.importNode(tmpElm,true));
			tmpElm=tmpElm.nextSibling;
		}
	}
	self.baseNode=baseNode;
	var	smark=self.smark=sMark.cloneNode(true),emark=self.emark=eMark.cloneNode(true);
	smark.innerHTML+=number+']';
	emark.innerHTML+=number+']';
	
	baseNode.insertBefore(emark,imark.nextSibling);
	baseNode.insertBefore(smark,emark);
	while (tmpElm=workDiv.firstChild) baseNode.insertBefore(tmpElm,emark);
	self.lockflg=false;
	setEventHandler(smark,'click',function(e){
		self.hide(e);
	});
	setEventHandler(emark,'click',function(e){
		self.hide(e);
		scrollIntoView(link);
	});
	setEventHandler(smark,'mousewheel',function(e){
		cancelBubble(e);
		if (!isWheelDown(e)) return false;
		scrollIntoView(emark);
	});
	setEventHandler(emark,'mousewheel',function(e){
		cancelBubble(e);
		if (isWheelDown(e)) return false;
		scrollIntoView(smark);
	});
	setEventHandler(link,'mouseover',function(e){
		self.appear(e);
	});
	setEventHandler(baseNode,'mousewheel',function(e){
		self.wheel(e);
	});
	self.ready=true;
};	//	end of ReadMoreObject.prototype.callback()

ReadMoreObject.prototype.hide=function(e){
	var	self=this;
	var	workDiv=self.workDiv;
	if (workDiv.firstChild) return;
	var	smark=self.smark;
	var	emark=self.emark;
	var	tmpElm;
	while (tmpElm=smark.nextSibling) {
		if (tmpElm==emark) break;
		workDiv.appendChild(tmpElm);
	}
	smark.style.display='none';
	emark.style.display='none';
	self.lockflg=true;
	setTimeout(function(){self.lockflg=false;},200);
};	//	end fo ReadMoreObject.prototype.hide()

ReadMoreObject.prototype.appear=function(e){
	var	self=this;
	var	workDiv=self.workDiv;
	if (!workDiv.firstChild) return;
	if (self.lockflg) return;
	var	smark=self.smark;
	var	emark=self.emark;
	var	baseNode=self.baseNode;
	var	tmpElm;
	while (tmpElm=workDiv.firstChild) baseNode.insertBefore(tmpElm,emark);
	smark.style.display='block';
	emark.style.display='block';
};	//	end of ReadMoreObject.prototype.appear()

ReadMoreObject.prototype.wheel=function(e){
	if (!e) e=w.event;
	if (!e.altKey&&!e.shiftKey&&!e.ctrlKey) return;
	var	self=this;
	var	workDiv=self.workDiv;
	if (workDiv.firstChild) return;
	cancelBubble(e);
	var	smark=self.smark;
	var	emark=self.emark;
	if (isWheelDown(e)) {
		scrollIntoView(emark);
	}
	else {
		scrollIntoView(smark);
	}
};	//	end of ReadMoreObject.prototype.wheel()

ReadMoreObject.prototype.toggle=function(e){
	var	self=this;
	var	workDiv=self.workDiv;
	self.lockflg=false;
	if (workDiv.firstChild) {
		self.appear();
	}
	else {
		self.hide();
	}
	scrollIntoView(self.link);
};	//	end of ReadMoreObject.prototype.toggle()

ReadMoreObject.prototype.toTop=function(e){
	var	self=this;
	if (self.workDiv.firstChild) return;
	scrollIntoView(self.smark);
};	//	end of ReadMoreObject.prototype.toTop()

ReadMoreObject.prototype.toBottom=function(e){
	var	self=this;
	if (self.workDiv.firstChild) return;
	scrollIntoView(self.emark);
};	//	end of ReadMoreObject.prototype.toBottom()


// === Main(Event Handling)
var	getReadMoreObj=function(link){
	var	number=link.getAttribute('_readmore_switch_no_');
	return (number)?readMoreObjs[number-1]:null;
};	//	end of getReadMoreObj()

var	createReadMoreObj=function(link){
	var	readMoreObj=getReadMoreObj(link);
	while (!readMoreObj) {
		if (link.getAttribute('_readmore_')) break;
		link.setAttribute('_readmore_',true);
		
		var	url='',aname='';
		if (link.href.match(/^(.*?)#(.*)$/)) {
			var	url=RegExp.$1,aname=RegExp.$2;
			if (!aname||!aname.match(regAnames)) break;
		}
		else {
			if (!forceCheckAtext) {
				var ci=0,len=checkAtextUrls.length;
				for (; ci<len; ci++) {
					if (curlocation.match(checkAtextUrls[ci])) break;
				}
				if (len<=ci) break;
			}
			if (!link.innerHTML.match(regAtexts)) break;
			url=link.href;
		}
		if (!url) break;
		if (sameDomainOnly&&!isSameDomain(url)) break;
		if (curlocation.replace(/#.*$/,'')==pathToUrl(url)) break;
	
		readMoreObj=new ReadMoreObject(link,url,aname);
		break;
	}
	return readMoreObj;
};	//	end of createReadMoreObj()

setEventHandler(d,'mouseover',function(e){
	if (!e) e=w.event;
	var	tgt=e.target||e.srcElement;
	while (tgt) {
		if (tgt.tagName&&tgt.tagName.toUpperCase()=='A') {
			try {
				var	self=createReadMoreObj(tgt);
			}
			catch(e){};
		}
		try {
			tgt=tgt.parentNode;
		}
		catch(e){
			break;
		}
	}
});

// === API functions
w.ReadMoreAPI={
	toggle		:	function(link){
		if (!link) return;
		var	readMoreObj=createReadMoreObj(link);
		if (readMoreObj) {
			if (readMoreObj.ready) {
				readMoreObj.toggle();
			}
//			else {
//				scrollIntoView(readMoreObj.link);
//			}
		}
	}
,	toTop		:	function(link){
		if (!link) return;
		var	readMoreObj=getReadMoreObj(link);
		if (readMoreObj&&readMoreObj.ready) readMoreObj.toTop();
	}
,	toBottom	:	function(link){
		if (!link) return;
		var	readMoreObj=getReadMoreObj(link);
		if (readMoreObj&&readMoreObj.ready) readMoreObj.toBottom();
	}
};

};	//	end of readmore()


// === Entry Point
if (typeof sleipnir!='undefined') {	//	SeaHorse
	_window.sleipnir=sleipnir;
	try{_window.execScript('('+readmore.toString()+')();','JavaScript');}catch(e){};
	_window.sleipnir=null;
}
else {			//	Greasemonkey
	readmore();
}

})();

