﻿// JavaScript Document
// 休診日カレンダー生成スクリプト Ver1.00(2010/03/11)
// Copyrightc Akitakenkouseiren. All right reserved.

// ■説明
//
// このスクリプトは、以下のパブリックメソッドを備え、処理機能を提供しています。
// (1)CalendarStart   : カレンダー再描画（下記(2)～(4)のメソッドから呼ばれるので、基本的には直接使用しない）
// (2)CalendarMoveNext: 基準月を+1としたカレンダー描画
// (3)CalendarMovePrev: 基準月を-1としたカレンダー描画
// (4)CalendarMoveNow : 基準月を現在の月としてカレンダーの描画
//
// これらのメソッドは、html上の以下のidを持ったdivタグ内にカレンダーを生成します。
// (基準月分)calendartop (基準月の翌月分)calendarbottom
// これらは必ず用意しておいてください。
//
// このスクリプトは、html上の以下のidのinputタグで基準月を保持します。
// (年)calendartargetyear (月)calendartargetmonth
// typeはhiddenで構いません。これらは必ず用意しておいてください。
//
// このスクリプトは、
// ・jQuery.js
// ・dateformat.js
// ・overLIB
// のスクリプトが必要です。必ず上記順番で追加したのち、本スクリプトを追加してください。
//
// overLIBは、
// <div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
// をbodyのどこかに記載する必要があります。この記載も忘れないでください。
//
// 次月・前月表示を行う場合は、それぞれ、CalendarMovePrev()ないしCalendarMoveNext()の呼び出しの必要があります。
// また、当月表示を行う場合は、CalendarMoveNow()の呼び出しが必要です。これはbody.onLoadで指定するべきです。

// ■権利
//
// このスクリプトは、JA秋田厚生連が設置ないし運営する病院のホームページに限り使用可能なものです。
// ソースコードの閲覧に制限はありませんし、参考になさっていただいても結構ですが、
// ソースコードの流用（再利用）、転載は、JA秋田厚生連の許諾がある場合を除いて、禁止とさせていただきます。

// ■プライベートなメソッド

// カレンダー書き出し処理（引数：対象西暦,対象月(1～12),書き出し対象divのid）
function zProcWriteCalendar(pYear, pMonth, pDiv) {
	
	var htmltext     = "";
	var currentid    = "";
	var currentfmt   = "";
	
	var dayclass     = "";
	var overlibhtml  = "";
	
	var rowcount     = new Number(0);
	
	// 日付書式オブジェクト：初期化
	var fmt   = new DateFormat("yyyyMMdd");
	var fmtym = new DateFormat("yyyyMM");
	var fmtol = new DateFormat("yyyy年MM月dd日");
	
	// 対象の年月：取得
	var targetYear = pYear;
	var targetMonth = pMonth;
	var targetDiv = pDiv;
	
	// 初日：設定
	var firstday = new Date(targetYear,targetMonth - 1,1);
	
	// 末日：設定
	var lastday  = new Date(targetYear,targetMonth,0);
	
	// カレント日：初期設定
	var currentday  = new Date(targetYear,targetMonth,1);
	
	// 祝日データ：読み込み
	var holidays = zGetHoliday();
	
	// 休診データ：読み込み
	var closes = zGetClose(fmtym.format(firstday));
	
	// 出力HTML領域：初期化
	htmltext = "";
	
	// テーブル開始.innerHTML
	htmltext += "<table class=\"calendar\">\n";
	htmltext += "<tbody>\n";
	
	htmltext += "<tr class=\"month\">\n";
	htmltext += "<td colspan=\"7\">" + new Number(firstday.getFullYear()) + "年 " + new Number(firstday.getMonth() + 1) + "月</td>\n";
	htmltext += "</tr>\n";
	
	htmltext += "<tr class=\"week\">\n";
	htmltext += "<th>日</th>\n";
	htmltext += "<th>月</th>\n";
	htmltext += "<th>火</th>\n";
	htmltext += "<th>水</th>\n";
	htmltext += "<th>木</th>\n";
	htmltext += "<th>金</th>\n";
	htmltext += "<th>土</th>\n";
	htmltext += "</tr>\n";
	
	// 行数初期化
	rowcount = 1;
	
	// 開始曜日に合わせて、空のデータタグを出力
	htmltext += "<tr class=\"days odd\">\n";
	for (var i = 1; i <= firstday.getDay(); i++) {
		htmltext += "<td class=\"blank\"></td>\n";
	}
	
	// 実際の日のデータタグを出力
	for (var i = 1; i <= lastday.getDate(); i++) {
		currentday = new Date(targetYear,targetMonth - 1,i);
		currentfmt = fmt.format(currentday);
		currentid = "cal" + currentfmt;
		
		dayclass = 'day';
		overlibhtml = '';
		
		// 休日クラスを付与するか否かの判定（祝日か、または土日であれば付与する）
		if (currentfmt in holidays) {
			dayclass += ' holiday';
		} else {
			if (currentday.getDay() == 0 || currentday.getDay() == 6) {
				dayclass += ' holiday';
			}
		}
		
		// 休診クラスを付与するか否かの判定（休診データがあれば付与する）
		if (currentfmt in closes) {
			dayclass += ' closeday';
		}
		
		// データタグの吐き出し
		if (currentfmt in closes) {
			htmltext += "<td class=\"" + dayclass + "\" id=\"" + currentid + "\">"
			htmltext += "<span";
			htmltext += " onMouseOver=\"return overlib('" + closes[currentfmt] + "', CAPTION, '" + fmtol.format(currentday) + "')\"";
			htmltext += " onMouseOut=\"return nd()\">";
			htmltext += i + "</span></td>";
		} else {
			htmltext +="<td class=\"" + dayclass + "\" id=\"" + currentid + "\">" + i + "</td>\n";
		}

		// 土曜日の出力の後であれば、行を閉じる（ただし末日の場合は行わない→後処理がやってくれるから）
		if (i != lastday.getDate()) {
			if (currentday.getDay() == 6) {
				rowcount += 1;
				if (rowcount % 2 == 1) {
					htmltext += "</tr>\n<tr class=\"days odd\">";
				} else {
					htmltext += "</tr>\n<tr class=\"days even\">";
				}
			}
		}
	}
	
	// 終了曜日に合わせて、空のデータタグを出力
	for (var i = lastday.getDay(); i < 6; i++) {
		htmltext += "<td class=\"blank\"></td>\n";
	}
	htmltext += "</tr>\n";
	
	// テーブル終了
	htmltext += "</tbody>\n";
	htmltext += "</table>\n";
	
	// カレンダー枠内にセット
	var obj = document.getElementById(targetDiv).innerHTML = htmltext;
	
}

// 祝日データ取得処理
function zGetHoliday() {
	
	// 格納配列：初期化
	var holidays = new Array;
	
	// xml取得
	var xmldata = $.ajax({
		url: "./xml/holiday.xml" ,
		cache: false ,
		dataType: "text/xml" ,
		async: false
	}).responseXML;	// 20100309 responseTextからresponseXMLに変更、cacheとdataTypeを追加
	
	// 格納配列：値をセット
	$(xmldata).find('items').find('item').each(function (){
		var idate = $(this).find('item-date:first').text();
		var iname = $(this).find('item-name:first').text();
		holidays[idate] = iname;
	});
	
	// 戻り値：格納配列を返す
	return holidays;
}

// 休診データ取得処理（年月をパラメータとして受け取ります。201004、といった形式です）
function zGetClose(ym) {
	
	// 格納配列：初期化
	var closes = new Array;
	
	// xml取得
	var xmldata = $.ajax({
		url: "./xml/close.xml" ,
		cache: false ,
		dataType: "text/xml" ,
		async: false
	}).responseXML;	// 20100309 responseTextからresponseXMLに変更、cacheとdataTypeを追加
	
	// 格納配列：値をセット
	// 全年月分を取得すると時間がかかり且つ無意味なので、対象年月の分のみ取得する
	$(xmldata).find('item-month#' + ym).each(function (){
		// 対象年月内のデータを順次取得する
		$(this).find('item').each(function (){
			var idate = $(this).find('item-date:first').text();
			var ihead = $(this).find('item-head:first').text();
			var ibody = $(this).find('item-body:first').text();
			
			// 同じ日のデータが既に格納済みの場合、末尾に追加していく
			// <h4>タグのスタイルについては呼び元htmlにて指定すること
			if (idate in closes) {
				closes[idate] += '<h4>' + ihead + '</h4>' + ibody;
			} else {
				closes[idate] = '<h4>' + ihead + '</h4>' + ibody;
			}
		});
	});
	return closes;
}

// ■パブリックなメソッド

function CalendarStart() {
	
	// 対象の年月を取得
	// とりあえずここでは直接入れているが、実際は外から値をもらう
	var targetyear  = new Number(document.getElementById('calendartargetyear').value);
	var targetmonth = new Number(document.getElementById('calendartargetmonth').value);
	
	// カレンダー生成関数呼び出し（当月）
	zProcWriteCalendar(targetyear, targetmonth, "calendartop");
	
	// カレンダー生成関数呼び出し（次月）
	zProcWriteCalendar(targetyear, targetmonth + 1, "calendarbottom");
	
	// OverLib初期設定
	zInitOverLib();
	
}

function CalendarMoveNext() {
	
	// 対象の年月を取得
	var targetyear  = new Number(document.getElementById('calendartargetyear').value);
	var targetmonth = new Number(document.getElementById('calendartargetmonth').value);
	
	// 次月に変更
	if (targetmonth == 12) {
		targetyear += 1;
		targetmonth = 1;
	} else {
		targetmonth += 1;
	}

	// 対象の年月を更新
	document.getElementById('calendartargetyear').value = targetyear;
	document.getElementById('calendartargetmonth').value = targetmonth;
	
	// カレンダー再描画
	CalendarStart();
	
}

function CalendarMovePrev() {
	
	// 対象の年月を取得
	var targetyear  = new Number(document.getElementById('calendartargetyear').value);
	var targetmonth = new Number(document.getElementById('calendartargetmonth').value);
	
	// 前月に変更
	if (targetmonth == 1) {
		targetyear -= 1;
		targetmonth = 12;
	} else {
		targetmonth -= 1;
	}

	// 対象の年月を更新
	document.getElementById('calendartargetyear').value = targetyear;
	document.getElementById('calendartargetmonth').value = targetmonth;
	
	// カレンダー再描画
	CalendarStart();
	
}

function CalendarMoveNow() {
	
	// 現在の年と月を取得
	var now = new Date();
	
	var targetyear  = now.getFullYear();
	var targetmonth = now.getMonth() + 1;
	
	// 対象の年月を更新
	document.getElementById('calendartargetyear').value = targetyear;
	document.getElementById('calendartargetmonth').value = targetmonth;
	
	// カレンダー再描画
	CalendarStart();
	
}
