<?xml version="1.0" encoding="UTF-8"?>
<Module>
<ModulePrefs title="今日は何の日？" title_url="http://shizlabs.amonya.com/igoogle/" description="今日の「記念日」、「出来事」、「誕生日」、「忌日」、「暦・祝日」を表示します（Wikipediaより）。カレンダーを表示して日付を変更することも可能です。" author="shiz" author_email="shiz.h.feedback+whatistoday@gmail.com" screenshot="http://www.amonya.com/igoogle/img/whatistoday_screen.png" thumbnail="http://www.amonya.com/igoogle/img/whatistoday_thumbnail.png" author_link="http://shizlabs.amonya.com/" height="180">
	<Require feature="tabs" />
	<Require feature="setprefs"/>
	<Require feature="dynamic-height"/>
</ModulePrefs>
<UserPref name="kinenbi" display_name="記念日" datatype="bool" default_value="true" />
<UserPref name="dekigoto" display_name="出来事" datatype="bool" default_value="true" />
<UserPref name="tanjobi" display_name="誕生日" datatype="bool" default_value="true" />
<UserPref name="imibi" display_name="忌日" datatype="bool" default_value="false" />
<UserPref name="koyomi" display_name="暦" datatype="bool" default_value="true" />
<UserPref name="page_num" display_name="表示数" datatype="enum" default_value="3">
	<EnumValue display_value="1" value="1" />
	<EnumValue display_value="2" value="2" />
	<EnumValue display_value="3" value="3" />
	<EnumValue display_value="4" value="4" />
	<EnumValue display_value="5" value="5" />
	<EnumValue display_value="6" value="6" />
	<EnumValue display_value="7" value="7" />
	<EnumValue display_value="8" value="8" />
	<EnumValue display_value="9" value="9" />
	<EnumValue display_value="10" value="10" />
</UserPref>
<UserPref name="detail" display_name="記念日詳細" datatype="enum" default_value="1">
	<EnumValue display_value="表示する" value="1" />
	<EnumValue display_value="表示しない" value="0" />
</UserPref>
<UserPref name="font_size" display_name="文字サイズ" datatype="enum" default_value="12">
	<EnumValue display_value="小" value="12" />
	<EnumValue display_value="中" value="14" />
	<EnumValue display_value="大" value="16" />
</UserPref>
<UserPref name="calender" datatype="hidden"/>
<UserPref name="selectedTab" datatype="hidden"/>
<Content type="html"><![CDATA[
<script type="text/javascript">
/*外部リソースをキャッシュで取得*/
document.write('<script type="text/javascript" src="'+_IG_GetCachedUrl('http://www.amonya.com/ecslib/xdom_mini.js')+'"></'+'script>');
</script>
<style>
a,a:link,a:visited,a:active {
	color:#000066;
}
a {
	text-decoration: none;
}
h2 {
	color:#000066;
	font-size:14px;
	font-weight:bold;
	margin:5px 3px;
}
h2 a{
	text-decoration: underline;
}

ul a,ul a:link,ul a:visited,ul a:active,
li a,ul a:link,li a:visited,li a:active{
	color:#000099;
}

ul {
	list-style-type: circle;
	margin: 0 0 3px 1em;
	padding: 0;
}

li {
	font-size:__UP_font_size__px;
}

p {
	margin:5px 3px;
	font-size:__UP_font_size__px;
}

#calender{
}
	#calender p {
		margin: 0;
	}
	#calender table {
		border:1px solid #888888;
		border-collapse:collapse;
		border-spacing:0;
		margin-left:auto;
		margin-right:auto;
	}
	#calender th {
		width:28px;
		font-weight:normal;
		font-size:12px;
		text-align:center;
		background-color:#aaaaff !important;
	}
	#calender td {
		font-size:12px;
		text-align:center;
	}
	#calender .month{
		font-size:14px;
		text-align:center;
		font-weight:bold;
		color:#000066;
	}
	#calender .now_date{
		background-color:#6666ff !important;
	}
	#calender .day0{
		background-color:#e0e0e0;
		color:red !important;
	}
	#calender .day6{
		background-color:#e0e0e0;
		color:red !important;
	}
	#calender .today{
		background-color:#888888;
	}
	#calender .other{
		color:#555555;
	}
	#calender .pointer{
		cursor: pointer;
	}

#content_div {
	margin:5px;
}
.page {
	text-align:center;
}
	.page p{
		margin-bottom:0px;
	}
	.page a{
		text-decoration: underline;
	}

.holiday{
	color:red !important;
}

.ctoggle{
		float:right;
		font-size:10px;
	}
.credit{
		float:left;
		font-size:11px;
}
</style>
<script type="text/javascript">
/*************************************************************/
/* 今日は何の日？ ver4.0.4                                   */
/* ファイル取得に失敗するケースが多い為、小細工追加          */
/* 煩雑になってきたので要ソース修正                          */
/*************************************************************/

/********** Wikipedia解析クラス **********/
var Wikipedia = function(current){
	var text = (new XDOM(current)).xpath('//page/revision/text').text();
	this.data = {};
	this.parse(text);
}

Wikipedia.prototype = {
	parse: function(text){
		var lines = ('== ヘッダー ==\n' + text).split('\n');
		
		var header = '';
		for (var i = 0, len = lines.length; i < len; i++){
			var line = lines[i];
			if (line.match(/^\=\= 関連項目 \=\=/)){
				return;
			}
			if (line.match(/^\{\{/)){
				continue;
			}else if (line.match(/^\=\=[^\=]/)){
				header = line.replace(/[\=\s\']/g, '');
				this.data[header] = [];
			}else if (line.match(/^\=\=\=[^\=]/)){
				continue;
			}else if (line.match(/^\;/)){
				this.data[header].push({'*':line.replace(/^\;/, ''), '**': [], '*:': []});
			}else if (line.match(/^\*[^\*\:]/)){
				this.data[header].push({'*':line.replace(/^\*\s*/, ''), '**': [], '*:': []});
			}else if (line.match(/^\:/)){
				this.data[header][this.data[header].length-1]['**'].push(line.replace(/^\:/, ''));
			}else if (line.match(/^\*\*/)){
				this.data[header][this.data[header].length-1]['**'].push(line.replace(/^\*\*\s*/, ''));
			}else if (line.match(/^\*\:/)){
				this.data[header][this.data[header].length-1]['*:'].push(line.replace(/^\*\:\s*/, ''));
			}
		}
	},
	isData: function(name){
		return this.data[name] ? true : false;
	}
};

/* Wikipediaリンク作成(staticメソッド) */
Wikipedia.getLineAddLink = function(line){
	var links = line.match(/\[\[[^\[\]]+\]\]/g);
	if (!links){return line};
	
	for (var i = 0; i < links.length; i++){
		var link = links[i].replace(/\[|\]/g, '');
		var temp = link.split('|');
		var title = temp[0];
		var name = temp[1] ? temp[1] : temp[0];
		line = line.replace(links[i], '<a href="http://ja.wikipedia.org/wiki/'+_esc(title)+'" title="'+title+'" target="_blank">'+name+'</a>');
	}
	return line;
}

/********** 今日は何の日 **********/
/* 定数 */
var BaseURL = 'http://ja.wikipedia.org/wiki/%E7%89%B9%E5%88%A5:Export/';
var LinkNames = {'記念日':'記念日・年中行事','出来事':'できごと','誕生日':'誕生日','忌日':'忌日'};
var WeekNamesJP = ['日', '月', '火','水','木','金','土'];
var LoadingImageURL = _IG_GetImageUrl('http://www.amonya.com/igoogle/img/loading.gif');

/* グローバル変数 */
var gPrefs = new _IG_Prefs(__MODULE_ID__);
var gTabs;
var gDate = new Date();
var gOldDate = null;
var gList = {};

/* 祝日 */
var gHoliday = {
	2008:{
		'2008-09-23': '秋分の日',
		'2008-03-20': '春分の日',
		'2008-11-24': '振替休日',
		'2008-07-21': '海の日',
		'2008-11-03': '文化の日',
		'2008-09-15': '敬老の日',
		'2008-01-14': '成人の日',
		'2008-05-03': '憲法記念日',
		'2008-02-11': '建国記念の日',
		'2008-12-23': '天皇誕生日',
		'2008-05-04': 'みどりの日',
		'2008-11-23': '勤労感謝の日',
		'2008-01-01': '元日',
		'2008-10-13': '体育の日',
		'2008-04-29': '昭和の日',
		'2008-05-05': 'こどもの日'
	},
	2009:{
		'2009-01-01': '元日',
		'2009-01-12': '成人の日',
		'2009-02-11': '建国記念の日',
		'2009-03-20': '春分の日',
		'2009-04-29': '昭和の日',
		'2009-05-03': '憲法記念日',
		'2009-05-04': 'みどりの日',
		'2009-05-05': 'こどもの日',
		'2009-05-06': '振替休日',
		'2009-07-20': '海の日',
		'2009-09-21': '敬老の日',
		'2009-09-22': '国民の休日',
		'2009-09-23': '秋分の日',
		'2009-10-12': '体育の日',
		'2009-11-03': '文化の日',
		'2009-11-23': '勤労感謝の日',
		'2009-12-23': '天皇誕生日'
	},
	2010:{
		'2010-01-01': '元日',
		'2010-01-11': '成人の日',
		'2010-02-11': '建国記念の日',
		'2010-03-21': '春分の日',
		'2010-03-22': '振替休日',
		'2010-04-29': '昭和の日',
		'2010-05-03': '憲法記念日',
		'2010-05-04': 'みどりの日',
		'2010-05-05': 'こどもの日',
		'2010-07-19': '海の日',
		'2010-09-20': '敬老の日',
		'2010-09-23': '秋分の日',
		'2010-10-11': '体育の日',
		'2010-11-03': '文化の日',
		'2010-11-23': '勤労感謝の日',
		'2010-12-23': '天皇誕生日'
	}
};

/* Wikipediaデータ取得 */
function search(time){
	if (gTabs.getTabs().length == 0){
		return;
	}
	gDate = time ? new Date(time) : gDate;
	
	var html = '';
/*
	html += '<p style="text-align:center;"><img src="'+LoadingImageURL+'" /></p>';
*/
	html += '<p>Loading...</p>';
	_gel('content_div').innerHTML = html;
	
	gList = {};
	var url = BaseURL + _esc((gDate.getMonth()+1) + '月' + gDate.getDate() + '日');
	url += '?timestamp='+_esc(getTimeStamp());
	_IG_FetchXmlContent(url, function(response){
		if (!response || typeof(response) != 'object' || !response.firstChild){
			_gel('content_div').innerHTML = '<p>データの取得に失敗しました。しばらく時間を空けてから再度更新してください。</p>';
			_IG_AdjustIFrameHeight();
			return;
		}
		var wiki = new Wikipedia(response);
		gList['記念日'] = wiki.data['記念日・年中行事'] || wiki.data['記念日'] || wiki.data['年中行事'] || [];
		gList['出来事'] = wiki.data['できごと'] || wiki.data['出来事'] || [];
		gList['出来事'] = gList['出来事'].reverse();
		gList['誕生日'] = wiki.data['誕生日'] || [];
		gList['誕生日'] = gList['誕生日'].sort(_sortBirthday);
		gList['忌日'] = wiki.data['忌日'] || wiki.data['忌み日'] || [];
		gList['忌日'] = gList['忌日'].reverse();
	
		if (gTabs.getSelectedTab().getName() != '暦・祝日'){
			output(0);
		}
	});
	
	if (gPrefs.getBool('koyomi')){
		koyomi_search();
	}
}

/* 誕生日降順ソート（競走馬、生年不明は末尾に移動）*/
function _sortBirthday(a, b){
	var a2 = a['*'].match(/(不詳)|(不明)|(競走馬)/) ? 0 : a['*'].match(/[0-9]+/);
	var b2 = b['*'].match(/(不詳)|(不明)|(競走馬)/) ? 0 : b['*'].match(/[0-9]+/);
	
	return b2 - a2;
}

/* データの出力（暦を除く） */
function output(start){
	var pageNum = gPrefs.getInt('page_num');
	var kind = gTabs.getSelectedTab().getName();
	var html = '';
	_gel('content_div').innerHTML = '';
	
	var d = (gDate.getMonth()+1) + '月' + gDate.getDate() + '日';
	var title = '';
	title += kind+' - '+d;
	html = '<h2>';
	html += '<a href="http://ja.wikipedia.org/wiki/'+_esc(d + '#'+LinkNames[kind])+'" target="_blank">';
	html += title;
	html += '</a>';
	html += '</h2>';
	
	if (!gList[kind] || !gList[kind].length || start > gList[kind].length){
		html += '<p>';
		html += kind+'はありません。';
		html += '</p>';
		_gel('content_div').innerHTML = html;
		_IG_AdjustIFrameHeight();
		return;
	}
	
	html += '<ul>';
	for (var i = start, len = gList[kind].length; i < start+pageNum && i < len; i++){
		if (gList[kind][i]['*']){
			html += '<li>'+Wikipedia.getLineAddLink(gList[kind][i]['*'])+'</li>';
			if (gPrefs.getInt('detail')){
				html += gList[kind][i]['**'].length > 0 ? '<ul>' : '';
				for (var j = 0, len2 = gList[kind][i]['**'].length; j < len2; j++){
					html += '<li>'+Wikipedia.getLineAddLink(gList[kind][i]['**'][j])+'</li>';
				}
				html += gList[kind][i]['**'].length > 0 ? '</ul>' : '';
				html += gList[kind][i]['*:'].length > 0 ? '<ul style="list-style-type:none;margin-left:0px;">' : '';
				for (var k = 0, len3 = gList[kind][i]['*:'].length; k < len3; k++){
					html += '<li>'+Wikipedia.getLineAddLink(gList[kind][i]['*:'][k])+'</li>';
				}
				html += gList[kind][i]['*:'].length > 0 ? '</ul>' : '';
			}
		}
	}
	html += '</ul>';
	html += _getPageHtml(start, pageNum, gList[kind].length);
	
	_gel('content_div').innerHTML = html;
	_IG_AdjustIFrameHeight();
}

/* ページ用HTMLの取得 */
function _getPageHtml(page_start, page_num, length){
	var html = '';
	if (page_num < length){
		html += '<div class="page">';
		html += '<p>';
		if (page_start == 0){
			html += '前へ';
		}else{
			html += '<a href="javascript:void(0);" onclick="output('+(page_start-page_num)+');return false;">前へ</a>';
		}
		html += '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
			if (length <= page_start+page_num){
			html += '次へ';
		}else{
			html += '<a href="javascript:void(0);" onclick="output('+(page_start+page_num)+');return false;">次へ</a>';
		}
		html += '</p>';
		html += '</div>';
	}
	return html;
}

/* 暦の検索 */
function koyomi_search(){
	gOldDate = null;
	var url = 'http://api.sekido.info/qreki?output=xml';
	url += '&year='+gDate.getFullYear();
	url += '&month='+(gDate.getMonth()+1);
	url += '&day='+gDate.getDate();
	
	_IG_FetchXmlContent(url, function(response){
		if (!response || typeof(response) != 'object' || !response.firstChild){
			_IG_AdjustIFrameHeight();
			return;
		}
		gOldDate = response;
		if (gTabs.getSelectedTab().getName() == '暦・祝日'){
			koyomi_output();
		}
	});
}

/* 暦の出力 */
function koyomi_output(){
	var html = '';
	
	html += '<h2>暦・祝日 - '+gDate.getFullYear()+'年'+(gDate.getMonth()+1) + '月' + gDate.getDate() + '日('+WeekNamesJP[gDate.getDay()]+')</h2>';

	html += '<ul>';
	var d1 = '平成' + (gDate.getFullYear() - 1988) + '年' + (gDate.getMonth()+1) + '月' + gDate.getDate() + '日';
	html += '<li>和暦：'+d1+'</li>';
	
	if(gOldDate){
		var old = new XDOM(gOldDate);
		var d2 = old.xpath('//rokuyou_text').text();
		var d3 = old.xpath('//text').text();
		html += '<li>旧暦：'+d3+'</li>';
		html += '<li>'+d2+'</li>';
	}
	if (gHoliday[gDate.getFullYear()]){
		var holiday = gHoliday[gDate.getFullYear()][gDate.getFullYear()+'-'+fillZero(gDate.getMonth()+1)+'-'+fillZero(gDate.getDate())];
		if (holiday){
			html += '<li><span class="holiday">'+holiday+'</span></li>';
		}
	}
	html += '</ul>';
	
	_gel('content_div').innerHTML = html;
	_IG_AdjustIFrameHeight();

}

/********** カレンダー **********/
/* カレンダーの表示 */
function showCalender(time){
	gPrefs.set('calender', 'true');
	outputCalender(time);
}

/* カレンダーの出力 */
function outputCalender(time){
	time = time ? time : gDate.getTime();
	gDate = new Date(time);
	var year = gDate.getFullYear();
	var month = gDate.getMonth()+1;
	var matrix = [];
	
	var date = new Date(year+'/'+month+'/1');
	date.setDate(date.getDate()-date.getDay());
	for (var i = 0; i < 6; i++){
		matrix[i] = [];
		for (var j = 0; j < 7; j++){
			var d = new Date(date.getTime());
			matrix[i].push(d);
			date.setDate(date.getDate()+1);
		}
	}
	var html = '';
	
	html += '<div style="text-align:center;">';
	var datePrev = new Date(time);
	datePrev.setMonth(gDate.getMonth()-1);
	datePrev.setDate(1);
	var dateNext = new Date(time);
	dateNext.setMonth(gDate.getMonth()+1);
	dateNext.setDate(1);
	html += '<p class="month">';
	html += '<span class="pointer" onclick="showCalender('+datePrev.getTime()+');search('+datePrev.getTime()+');">&lt;&lt;</span>　　';
	html += year+'年'+month+'月';
	html += '　　<span class="pointer" onclick="showCalender('+dateNext.getTime()+');search('+dateNext.getTime()+');"">&gt;&gt;</span>';
	html += '</p>';
	html += '<p>';
	html += '<table>';
	html += '<tr>';
	for (var i = 0; i < 7; i++){
		html += '<th class="day'+i+'">';
		html += WeekNamesJP[i];
		html += '</th>';
	}
	html += '</tr>';
	for (var i = 0; i < matrix.length; i++){
		html += '<tr>';
		for (var j = 0; j < matrix[i].length; j++){
			var day = matrix[i][j];
			html += '<td onclick="showCalender('+day.getTime()+');search('+day.getTime()+');"';
			html += ' class="pointer day'+j;
			if (day.getMonth() == gDate.getMonth() &&
					day.getDate() == gDate.getDate()){
				html += ' now_date';
			}
			var now = new Date();
			if (day.getMonth() == now.getMonth() &&
					day.getDate() == now.getDate()){
				html += ' today';
			}
			if (gHoliday[gDate.getFullYear()] && gHoliday[gDate.getFullYear()][day.getFullYear()+'-'+fillZero(day.getMonth()+1)+'-'+fillZero(day.getDate())]){
				html += ' holiday';
			}
			if (day.getMonth() != gDate.getMonth()){
				html += ' other';
			}
			html += '">';
			html += day.getDate();
			html += '</td>';
		}
		html += '</tr>';
	}
	html += '</table>';
	html += '</p>';
	html += '</div>';
	html += '<div style="width:100%;">';
	html += '<div class="credit"><a href="http://shizlabs.amonya.com/" target="_blank">Shiz Labs</a></div>';
	html += '<div class="ctoggle"><a href="javascript:void(0);" onclick="hideCalender();">カレンダーを閉じる</a></div>';
	html += '<div style="clear:both;"></div>';
	html += '</div>';
	
	_gel('calender').innerHTML = html;
	_IG_AdjustIFrameHeight();
}

/* カレンダーの非表示 */
function hideCalender(){
	gPrefs.set('calender', 'false');
	
	var html = '';
	html += '<div style="width:100%;">';
	html += '<div class="credit"><a href="http://shizlabs.amonya.com/" target="_blank">Shiz Labs</a></div>';
	html += '<div class="ctoggle"><a href="javascript:void(0);" onclick="showCalender();">カレンダーを開く</a></div>';
	html += '<div style="clear:both;"></div>';
	html += '</div>';
	_gel('calender').innerHTML = html;
	_IG_AdjustIFrameHeight();
}

/********** 共通 **********/
/* 1桁の数字を2桁にする。それだけ */
function fillZero(num){
	return (num < 10) ? '0'+num : num;
}

/* バグ回避用タイムスタンプ */
function getTimeStamp(){
	var now = new Date();
	var year = now.getFullYear();
	var month = fillZero(now.getMonth()+1);
	var date = fillZero(now.getDate());
	var hours = now.getHours();
	var minutes = now.getMinutes();
	return year+'-'+month+'-'+date+'-'+hours+':'+minutes;
}

/********** 初期処理 **********/
window.onload = function(){
	gTabs = new _IG_Tabs(__MODULE_ID__, 0, _gel('tabs'));
	if (gPrefs.getBool('kinenbi')){
		gTabs.addDynamicTab('記念日', function(){output(0);});
	}
	if (gPrefs.getBool('dekigoto')){
		gTabs.addDynamicTab('出来事', function(){output(0);});
	}
	if (gPrefs.getBool('tanjobi')){
		gTabs.addDynamicTab('誕生日', function(){output(0);});
	}
	if (gPrefs.getBool('imibi')){
		gTabs.addDynamicTab('忌日', function(){output(0);});
	}
	if (gPrefs.getBool('koyomi')){
		gTabs.addDynamicTab('暦・祝日', koyomi_output);
	}
	if (gTabs.getTabs().length > 0){
			search();
	}
	if (gPrefs.getBool('calender')){
		showCalender();
	}else{
		hideCalender();
	}
};
</script>
<div id="calender"></div>
<div id="tabs"></div>
<div id="content_div"></div>
]]></Content>
</Module>
