/********************************************************************************

	RSSフィーダー
		作成者	Masashi Kikkawa

	【説明】
		複数のフィードをマージすることも可能。
		各種設定は「rss_feeder_config.js」に記述。
		※外部ドメインのフィードを取得する場合はGoogle AJAX Feed API版を使用すること

	【更新履歴】
		2008.07.29 v.1.00
			公開。

********************************************************************************/




//_______________________________________________________________________________
//	RSSフィーダー
var	eoFeeder	=	new class_eoFeeder();
function	class_eoFeeder()
{
	this.objOnload	=	window.onload;	//	既存のonloadイベント

	//	変数
	this.aRequest		=	[];	//	HttpRequestオブジェクト一覧
	this.aFeedIDList	=	[];	//	読み込むフィードID一覧
	this.aFeedList		= 	[];	//	読み込むフィード一覧

	//___________________________________________________________________________
	//	RSSフィーダー初期化
	this.Init	=	function()
	{
		//	既存のonLoadイベントを実行
		if( this.objOnload != null )	this.objOnload();

		//	各ID別に処理
		for( var i=0; i<this.aFeedIDList.length; i++ )
		{
			//	フィードIDチェック
			if( !document.getElementById( this.aFeedIDList[i] ) )
			{
				this._Alert( 'Init', 'フィードID ' + this.aFeedIDList[i] + ' がHTML上に見つかりません。' );
			}
			else
			{
				//	各フィードを読み込み
				for( var j=0; j<this.aFeedList[this.aFeedIDList[i]].aRssList.length; j++ )
				{
					this._LoadFeed( this.aFeedIDList[i], this.aFeedList[this.aFeedIDList[i]].aRssList[j] );
				}
			}
		}
	};

	//___________________________________________________________________________
	//	フィードをセット
	this.SetFeed	=	function( vID, vEntryCnt, aRssList, funcCallback )
	{
		this.aFeedIDList[this.aFeedIDList.length]	=	vID;
		this.aFeedList[vID]							=	new class_eoFeed( vEntryCnt, aRssList, funcCallback );
	};

	//___________________________________________________________________________
	//	フィードの読み込み
	this._LoadFeed	=	function( vID, vRss )
	{
		var	vReqIdx	=	this.aRequest.length;

		this.aRequest[vReqIdx]	=	this._createXMLHttpRequest( vID, vReqIdx, this._getXML );

		if( this.aRequest[vReqIdx] )
		{
			this.aRequest[vReqIdx].open( 'GET', vRss, true );
			this.aRequest[vReqIdx].send( null );
		}
	};

	//___________________________________________________________________________
	//	読み込み完了処理
	this._Loaded	=	function( vID, xmlRes )
	{
		var	vVer	=	'';
		var	vRss	=	xmlRes.getElementsByTagName( 'rss' );
		var	vItems	=	xmlRes.getElementsByTagName( 'item' );
		var	vTmp	=	'';

		//	RSSバージョンを取得
		if( xmlRes.getElementsByTagName( 'rss' )[0] )
		{
			vVer	=	xmlRes.getElementsByTagName( 'rss' )[0].getAttribute( 'version' );
		}
		else if( xmlRes.getElementsByTagName( 'rdf:RDF' )[0] )
		{
			vVer	=	xmlRes.getElementsByTagName( 'rdf:RDF' )[0].getAttribute( 'xmlns' ).match( /http:\/\/purl.org\/rss\/([0-9.]+)\// )[1];
		}

		//	RSSをパース
		for( var i=0; i<vItems.length && i<this.aFeedList[vID].vEntryCnt; i++ )
		{
			var	vTitle		=	'';
			var	vLink		=	'';
			var	vContent	=	'';
			var	vDate		=	'';
			var	vCtgry		=	'';
			var	vCreator	=	'';

			//	各値を取得
			for( var j=0; j<vItems[i].childNodes.length; j++ )
			{
				switch( vItems[i].childNodes[j].nodeName )
				{
				case	'title':
					if( vItems[i].childNodes[j].firstChild )
					{
						vTitle	=	vItems[i].childNodes[j].firstChild.nodeValue;
					}
					break;
				case	'link':
					if( vItems[i].childNodes[j].firstChild )
					{
						vLink	=	vItems[i].childNodes[j].firstChild.nodeValue;
					}
					break;
				case	'description':
					if( vItems[i].childNodes[j].firstChild )
					{
						if( vVer != 1.0 )
						{	//	1.0の場合はcontent:encodedから取得
							vContent	=	vItems[i].childNodes[j].firstChild.nodeValue;
						}
					}
					break;
				case	'content:encoded':
					if( vItems[i].childNodes[j].firstChild )
					{
						vContent	=	vItems[i].childNodes[j].firstChild.nodeValue;
					}
					break;
				case	'pubDate':
					if( vItems[i].childNodes[j].firstChild )
					{
						if( vVer != 1.0 )
						{	//	1.0の場合はdc:dateから取得
							vDate	=	new Date( vItems[i].childNodes[j].firstChild.nodeValue );
						}
					}
					break;
				case	'dc:date':
					if( vItems[i].childNodes[j].firstChild )
					{
						var	aDateTmp	=	vItems[i].childNodes[j].firstChild.nodeValue.match( /^([0-9]+?)-([0-9]+?)-([0-9]+?)T([0-9]+?):([0-9]+?):([0-9]+)/ );
						vDate			=	new Date( aDateTmp[1], aDateTmp[2]-1, aDateTmp[3], aDateTmp[4], aDateTmp[5], aDateTmp[6] );
					}
					break;
				case	'dc:subject':
					if( vItems[i].childNodes[j].firstChild )
					{
						vCtgry	=	vItems[i].childNodes[j].firstChild.nodeValue;
					}
					break;
				case	'dc:creator':
					if( vItems[i].childNodes[j].firstChild )
					{
						vCreator	=	vItems[i].childNodes[j].firstChild.nodeValue;
					}
					break;
				}
			}

			//	エントリをストック
			this.aFeedList[vID].aLoadEntry[this.aFeedList[vID].aLoadEntry.length]	=	new class_eoEntry( vTitle, vLink, vContent, vDate, vCtgry, vCreator );
		}

		//	読み込み完了フィード数をカウント
		this.aFeedList[vID].vLoadCnt	+=	1;

		//	全フィード読み込み判定
		if( this.aFeedList[vID].vLoadCnt < this.aFeedList[vID].aRssList.length )
		{	//	リスト分読み込んでなければ終了
			return;
		}

		//	各エントリを更新日時で降順ソート
		for( var i=0; i<this.aFeedList[vID].aLoadEntry.length-1; i++ )
		{
			for( var j=0; j<this.aFeedList[vID].aLoadEntry.length-1-i; j++ )
			{
				if( this.aFeedList[vID].aLoadEntry[j].vDate < this.aFeedList[vID].aLoadEntry[j+1].vDate )
				{
					var	vEntryTmp						=	this.aFeedList[vID].aLoadEntry[j];
					this.aFeedList[vID].aLoadEntry[j]	=	this.aFeedList[vID].aLoadEntry[j+1];
					this.aFeedList[vID].aLoadEntry[j+1]	=	vEntryTmp;
				}
			}
		}

		//	コールバックの実行
		if( this.aFeedList[vID].funcCallback )	this.aFeedList[vID].funcCallback( vID, this.aFeedList[vID].aLoadEntry );
	};

	//___________________________________________________________________________
	//	警告表示
	this._Alert	=	function( vMethodName, vMsg )
	{
		alert( '【RSSフィーダーエラー】\n（' + vMethodName + '）\n\n' + vMsg );
	};

	//_______________________________________________________________________________
	//	XMLを取得
	this._getXML	=	function( vID, vReqIdx )
	{
		if( eoFeeder.aRequest[vReqIdx].readyState == 4 )
		{
			switch( eoFeeder.aRequest[vReqIdx].status )
			{
			case 200:
				if( eoFeeder.aRequest[vReqIdx].responseXML )
				{
					eoFeeder._Loaded( vID, eoFeeder.aRequest[vReqIdx].responseXML );
				}
				else
				{
					eoFeeder._Alert( '_getXML', 'XMLが取得できません。' );
				}
				break;
			case 403:
				eoFeeder._Alert( '_getXML', 'アクセスが拒否されました。' );
				break;
			case 404:
				eoFeeder._Alert( '_getXML', 'ファイルがありません。' );
				break;
			default:
				eoFeeder._Alert( '_getXML', '原因不明のエラーが発生しました。（' + eoFeeder.aRequest[vReqIdx].status + '）' );
				break;
			}
		}
	};

	//_______________________________________________________________________________
	//	HttpRequestオブジェクトを生成
	this._createXMLHttpRequest	=	function( vID, vReqIdx, funcGetXML )
	{
		var	XMLhttpObject	=	null;

		try
		{
			XMLhttpObject	=	new XMLHttpRequest();
		}
		catch( e )
		{
	 		try
			{
				XMLhttpObject	=	new ActiveXObject( 'Msxml2.XMLHTTP' );
			}
			catch( e )
			{
				try
				{
					XMLhttpObject	=	new ActiveXObject( 'Microsoft.XMLHTTP' );
				}
				catch( e )
				{
					return	null;
				}
			}
		}

		if( XMLhttpObject )	XMLhttpObject.onreadystatechange	=	function(){ funcGetXML( vID, vReqIdx ) };

		return	XMLhttpObject;
	};

	//___________________________________________________________________________
	//	フィードクラス
	function	class_eoFeed( vEntryCnt, aRssList, funcCallback )
	{
		this.vEntryCnt		=	vEntryCnt;
		this.aRssList		=	aRssList;
		this.funcCallback	=	funcCallback;
		this.aLoadEntry		=	[];
		this.vLoadCnt		=	0;
	};

	//___________________________________________________________________________
	//	エントリクラス
	function	class_eoEntry( vTitle, vLink, vContent, vDate, vCtgry, vCreator  )
	{
		this.vTitle		=	vTitle;
		this.vLink		=	vLink;
		this.vContent	=	vContent;
		this.vDate		=	vDate;
		this.vCtgry		=	vCtgry;
		this.vCreator	=	vCreator;
	};
}




//_______________________________________________________________________________
//	window.onloadにセット
window.onload	=	function()
{
	//	RSSフィーダー初期化
	eoFeeder.Init();
}





