/*==============================================================================
	Haloscan による Recent Comments クラス

	$Id$
	Copyright (C) 2005 OKAMURA Yuji, All rights reserved.
==============================================================================*/
/*
 * 顔文字クラス
 * @param str	顔文字の文字列
 * @param img	顔文字の画像のファイル名
 */
function CHaloFace(str, img) {
	this.m_Str = str;
	this.m_ImgURL = 'http://www.haloscan.com/images/smileys/'+img;
}

/*---- 静的属性 ----*/

/*
 * 顔文字のリスト
 */
CRCHalo_M_Face = new Array;
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':)', 'content.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	';)', 'clin_oeil.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':(', 'pascontent.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':lol:', 'lol.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':o(', 'pas_sourire.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	'8)', 'soleil.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':?:', 'question.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':+:', 'cool.gif'
);
CRCHalo_M_Face[CRCHalo_M_Face.length] = new this.CHaloFace(
	':-:', 'pas_cool.gif'
);

/*---- 静的メソッド ----*/
/*
 * Haloscan による Recent Comments クラス
 * @param url	RSS の URL,
 * @param welmt	RSS Feed を書き出す HTML の DOM ノード
 * @param async	非同期で動作させるかどうか(オプション)
 */
function CRCHalo(url, welmt, async) {
	/*---- 基底クラスのコンストラクタ ----*/
	this.CRssFeed = CRssFeed;
	this.CRssFeed(url, welmt, async);

	/*---- メンバー変数 ----*/
	/*
	 * コメントがないときの文言
	 */
	this.m_NoCommentsMessage = '誰かコメントください (T_T)';

	/*
	 * 顔文字をアイコン化するかどうか
	 */
	this.m_UseFaceIcon = true;

	/*
	 * コメントのアンカー名の prefix
	 */
	this.m_AnchorPrefix = '';

	/*
	 * コメントのアンカー名の postfix
	 */
	this.m_AnchorPostfix = '';

	/*---- メソッド ----*/
	// 外部インターフェースを意図

	// 下位クラスで書き換えを意図

	/*
	 * RSS 出力用の HTML を生成する
	 * @param channel	channel 要素をハッシュ化したもの
	 * @return HTML を表す文字列
	 */
	this.RssHTML = CRCHalo_RssHTML;

	/*
	 * item 出力用の HTML を生成する
	 * @param itemIdx	何番目のアイテムか
	 * @param channel	channel 要素をハッシュ化したもの
	 * @return HTML を表す文字列
	 */
	this.ItemHTML = CRCHalo_ItemHTML;

	/*
	 * コメントの属性を取得する。
	 * @param title	コメントのタイトル
	 * @return コメントの属性から属性値へのハッシュ
	 */
	this.CommentAttr = CRCHalo_CommentAttr;

	// このクラスおよび下位クラスでの使用を意図

	/*
	 * アンカー名を補正する<br>
	 * 各コメントのアンカー名はデフォルトでは数字のみで invalid である。
	 * このため、テンプレートを編集して前後に文字列を付けてい補正している場合は
	 * リンクを補正しなければならない。
	 * @param url	コメントの URL オリジナル
	 * @return コメントの補正された URL
	 */
	this.CommentURL = CRCHalo_CommentURL;

	/*
	 * テキストをなるべくそのまま表示する HTML に変換する<br>
	 * テキスト表示するときに使用する。
	 * @param text	HTML に変換するテキスト
	 * @return HTML(文字列)
	 */
	this.Text2HTML = CRCHalo_Text2HTML;

	// このクラスでのみ使用を意図
}

/*---- メソッドの実装 ----*/
function CRCHalo_CommentURL(url) {
	if (this.m_AnchorPrefix != '' || this.m_AnchorPostfix != '') {
		if (url.match(/^(.*)#(\d+)$/)) {
			url = RegExp.$1 + '#' + this.m_AnchorPrefix + RegExp.$2 + this.m_AnchorPostfix;
		}
	}

	return url;
}

function CRCHalo_Text2HTML(text) {
	text = text.replace(/^\n+/, '');
	text = text.replace(/[ \t\n\r]+$/, '');
	text = text.replace(/ /g, '&nbsp;');
	text = text.replace(/\t/g, '&#9;');
	text = text.replace(/\n/g, '<br />');
	if (this.m_UseFaceIcon) {
		var	i;

		for (i = 0; i < CRCHalo_M_Face.length; i++) {
			while (text.indexOf(CRCHalo_M_Face[i].m_Str) >= 0) {
				text = text.replace(
					CRCHalo_M_Face[i].m_Str,
					'<img src="'+CRCHalo_M_Face[i].m_ImgURL+'" width="15" height="15" border="0" alt=" " />'
				);
			}
			text = text.replace(
				/alt=" "/g,
				'alt="'+this.SafeHTMLAttrText(CRCHalo_M_Face[i].m_Str)+'"'
			);
		}
	}

	return text;
}

function CRCHalo_CommentAttr(title) {
	var	hash = new Array();
	var	i;

	if (!title.match(/^Thread: ([^.]+)\. Post by (.*)$/)) {
		return hash;
	}
	hash['thread'] = RegExp.$1;
	hash['post'] = RegExp.$2;

	return hash;
}

function CRCHalo_RssHTML(channel) {
	var	html;
	var	i;
	var	cnt = 0;

	html = '<dl>';
	for (i = 0; i < channel['item'].length; i++) {
		var	itemHtml = this.ItemHTML(i, channel);

		if (itemHtml != '') {
			html += itemHtml;
			cnt++;
		}
	}
	html += '</dl>';

	if (cnt == 0) {
		html = this.m_NoCommentsMessage;
	}

	return html;
}

function CRCHalo_ItemHTML(itemIdx, channel) {
	var	html;
	var	hash;

	// コメントの属性を取得する
	hash = this.CommentAttr(channel['item'][itemIdx]['title']);

	// アイテム(コメント)用の HTML を生成する。
	html = '<dt>'
		+ '<a href="'
		+ this.SafeHTMLAttrText(this.CommentURL(
			channel['item'][itemIdx]['link']
		  ))
		+ '">'
		+ this.SafeHTMLText(hash['thread'])
		+ ' : '
		+ this.SafeHTMLText(hash['post'])
		+ '</a>'
		+ '</dt>'
		+ '<dd>'
		+ this.Text2HTML(channel['item'][itemIdx]['description'])
		+ '</dd>'
	;

	return html;
}
