document.write( "<script type='text/JavaScript' src='./script/holiday.js'></script>" ) ;	/*	holiday.jsのinclude	*/


var		DEF_DATES_PER_WEEK = 7 ;


var		DEF_CALENDAR_DAY_LABEL_NON = 0 ;		/*	カレンダー見出し：なし	*/
var		DEF_CALENDAR_DAY_LABEL_JPN = 1 ;		/*	カレンダー見出し：日	*/
var		DEF_CALENDAR_DAY_LABEL_ENG = 2 ;		/*	カレンダー見出し：英	*/


var		DEF_CALENDAR_DATE_KIND_WEEKDAY	= 0 ;	/*	一般日	*/
var		DEF_CALENDAR_DATE_KIND_SATURDAY	= 1 ;	/*	土曜日	*/
var		DEF_CALENDAR_DATE_KIND_SUNDAY	= 2 ;	/*	日曜日	*/
var		DEF_CALENDAR_DATE_KIND_HOLIDAY	= 3 ;	/*	祝祭日	*/




/**
 * コンストラクタ。
 * マークアップカレンダークラス。
 *
 * @param	year	対象の年。
 *			month	対象の月。
 */
function ExtCalendar( year, month ) {

	if( typeof(year) == "undefined" || typeof(year) == "month"  ) {
		alert( "引数が未定義" ) ;
	}

	/*	年情報セット	*/
	if( isNaN( year ) == NaN ) {
		alert("年指定が有効でない\n[" + year + "]") ;
	}
	else {
		this.year = parseInt( year, 10 ) ;
	}

	/*	月情報セット	*/
	if( isNaN( month ) == NaN ) {
		alert("月指定が有効でない\n[" + month + "]") ;
	}
	else {
		this.month = parseInt( month, 10 ) ;
		if( this.month<1 || this.month>12 ) {
			alert("設定可能な月指定である\n[" + month + "]") ;
			if ( this.month<1 ) {	this.month = 1 ;	}
			if ( this.month>12 ) {	this.month = 12 ;	}
		}
	}


	/*	該当月の開始曜日をセットする	*/
	this.startDay = (new Date(this.year,this.month-1,1)).getDay() ; 

	/*	該当月の開始日（通常は１）	*/
 	this.startDate = 1 ;

	/*	該当月の最後の日をセットする	*/
 	this.setLastDate() ;	/*	this.lastDate	*/


	/*	表示スタイル（ディフォルト）	*/
	this.setDispStyle( "calendar" ) ;

	/*	曜日見出し表示（日）する	*/
	this.setDayLabelJpn() ;

	/*	有効期間：ディフォルトで１～最終日まで	*/
	this.validyTermStart = this.startDate ;
	this.validyTermLast = this.lastDate ;

}


/**
  *オブジェクトのデバッグ情報を表示する。
 */
ExtCalendar.prototype.debug = function () {
	var		info="" ;
	var		ii ;
	info += "year = " + this.year + "\n" ;
	info += "month = " + this.month + "\n" ;

	info += "holiday = " ;
	if( typeof(this.holidayNum) == "undefined" || this.holidayNum==0 ) {
		info += "none" ;
	}
	else {
		for( ii=0; ii<this.holidayNum; ii++ ) {
			info += this.holiday[ii] ;
			if( ii<this.holidayNum-1 ) {
				info += ", " ;
			}
		}
	}
	info += "\n" ;
	info += "style [" + this.style + "]\n" ;
	info += "title [" + this.title + "]\n" ;

	alert( info ) ;
}


/**
 * 該当月の最後の日をセットする。
 *
 */
ExtCalendar.prototype.setLastDate = function () {
	var		lastDateInfo = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

	this.lastDate = lastDateInfo[ this.month - 1 ] ;

	/*	閏年の処理	*/
	if( this.isLeapYear()==true ) {
		this.lastDate = 29 ;
	}
}


/*
 *	有効期間をセットする。
 *
 *	@param	start	有効期間：先頭
 *			end		有効期間：後端
 *
 */
ExtCalendar.prototype.setValidyTerm = function ( start, end ) {
	var		date1, date2 ;

	/*	引数がない場合はディフォルト設定	*/
	if( typeof(start)=="undefined" ) {
		alert( "有効表示範囲：開始日が未定義" ) ;
		return ;
	}


	if( isNaN(start) ) {
		alert( "有効表示範囲：開始日が数値ではない\n[" + start + "]" ) ;
		return ;
	}
	if( isNaN(end) ) {
		alert( "有効表示範囲：終了日が数値ではない\n[" + end + "]" ) ;
		return ;
	}


	validStart = parseInt( start, 10 ) ;
	validEnd = parseInt( end, 10 ) ;

	if( validStart>validEnd ) {
		/*	開始日と最終日の関係が逆転	*/
		alert(
			"開始日と最終日の関係が逆転\n" +
			sprintf( "start: %2d\end  : %2d", validStart, validEnd ) 
		) ;
		return ;
	}

	if(
		validStart<this.startDate || validStart>this.lastDate ||
		validEnd<this.startDate || validEnd>this.lastDate
	) {
		/*	該当月の開始日／最終日外を指定している	*/
		alert(
		
			"有効表示範囲設定が該当月の開始日／最終日範囲外\n" +
			sprintf( "available: %2d - %2d\n", this.startDate, this.lastDate ) +
			sprintf( "new range: %2d - %2d", validStart, validEnd ) 
		) ;
		return ;
	}
	else {
		this.validyTermStart = validStart ;
		this.validyTermLast = validEnd ;
	}
}


/**
  * 表示スタイルを定義する。
  * 
  * @param	style	メニューバーを表示するスタイルのスタイル名。
  */
ExtCalendar.prototype.setDispStyle = function ( style ) {
	this.style = style ;
	return( this.style ) ;
}

/**
 * 該当月の開始曜日をセットする。
 *
 */
ExtCalendar.prototype.setTitle = function ( title ) {	this.title = title ;	}

/**
 * 曜日見出し表示（日）する。
 */
ExtCalendar.prototype.setDayLabelJpn = function () {	this.dayLabel = DEF_CALENDAR_DAY_LABEL_JPN ;	}

/**
 * 曜日見出し表示（英）する。
 */
ExtCalendar.prototype.setDayLabelEng = function () {	this.dayLabel = DEF_CALENDAR_DAY_LABEL_ENG ;	}

/**
 * 曜日見出し表示しない。
 */
ExtCalendar.prototype.resetDayLabel = function () {	this.dayLabel = DEF_CALENDAR_DAY_LABEL_NON ;	}


/**
 * 閏年に該当するかどうか返す。
 *
 * @return 閏年の場合は<code>true</code>、それ以外は<code>false</code>を返す。
 */
ExtCalendar.prototype.isLeapYear = function ()
{
	if(this.month==2){
		if(this.year%4==0){
			if( !( (this.year%100==0) && (this.year%400!=0) ) ){
				return( true ) ;
			}
		}
	}
	return( false ) ;
}


ExtCalendar.prototype.isHoliday = function (date)
{
	var		ii ;
	var		tmp ;
	if( typeof(fHolidayScriptCheck)=="undefined" ) {
		alert( "this html needs holiday.js." ) ;
		fHolidayScriptCheck = true ;
		return( false ) ;
	}
	else {
		tmp = sprintf( "%04d/%02d/%02d", this.year, this.month, date ) ;
		return( isHoliday( new Date(tmp) ) ) ;
	}
}


/**
 *	カレンダー見出し表示文字列を取得する。
 */
ExtCalendar.prototype.getDayHeadWord = function ()
{
	var		msg="" ;
	var		day ;
	var		headJpn = new Array( "日" ,"月" ,"火" ,"水" ,"木" ,"金" ,"土" ) ;
	var		headEng = new Array( "Sun" ,"Mon" ,"Tue" ,"Wed" ,"Thr" ,"Fri" ,"Sat" ) ;
	var		headSize = headJpn.length ;


	/*	カレンダー見出し処理	*/
	if( this.dayLabel==DEF_CALENDAR_DAY_LABEL_NON ) {
		/*	カレンダー見出し：なし(0)ならreturn	*/
		return( msg ) ;
	}


	msg += "<tr>" ;
	for( day=0; day<headSize; day++ ) {
		msg += sprintf( "<th class='%s'>%s</td>",
					this.getHeaderStyleClass( this.getUnitDateKind(0,day) ),
					( ( this.dayLabel==DEF_CALENDAR_DAY_LABEL_ENG ) ? headEng[day] : headJpn[day] )
				) ;
	}
	msg += "</tr>" ;

	return( msg ) ;
}


/**
 * カレンダの各日の表示スタイルコードを取得する。
 *
 *	@return		表示スタイルコード。
 *					DEF_CALENDAR_DATE_KIND_WEEKDAY		一般日(0)
 *					DEF_CALENDAR_DATE_KIND_SATURDAY		土曜日(1)
 *					DEF_CALENDAR_DATE_KIND_SUNDAY		日曜日(2)
 *					DEF_CALENDAR_DATE_KIND_HOLIDAY		祝祭日(3)
 */
ExtCalendar.prototype.getUnitDateKind = function ( date, day )
{
	var		code ;
	if( this.isHoliday(date) ) {
		/*	祝祭日である	*/
		return( DEF_CALENDAR_DATE_KIND_HOLIDAY ) ;
	}

	/*	一般日	*/
	switch( day ) {
	case 0:		code = DEF_CALENDAR_DATE_KIND_SUNDAY ;		break ;
	case 6:		code = DEF_CALENDAR_DATE_KIND_SATURDAY ;	break ;
	default:	code = DEF_CALENDAR_DATE_KIND_WEEKDAY ;		break ;	/*	including  1, 2, 3, 4, 5	*/
	}
	return( code ) ;
}


/**
 * カレンダのヘッダの<td>タグ表示スタイル名を取得する。
 *
 *	@return		表示スタイルクラス名
 *					saturday	一般日(0)
 *					weekday	土曜日(1)
 *					sunday		日曜日(2)
 *					holiday	祝祭日(3)
 */
ExtCalendar.prototype.getHeaderStyleClass = function ( kind )
{
	return( this.getUnitDateStyleClass( kind ) ) ;
}


/**
 * カレンダの各日の<td>タグ表示スタイル名を取得する。
 *
 *	@return		表示スタイルクラス名
 *					saturday	一般日(0)
 *					weekday		土曜日(1)
 *					sunday		日曜日(2)
 *					holiday		祝祭日(3)
 */
ExtCalendar.prototype.getUnitDateStyleClass = function ( kind )
{
	var		style ;
	switch( kind ) {
	case DEF_CALENDAR_DATE_KIND_SATURDAY:	style = "saturday" ;	break ;	/*	土曜日(1)	*/
	case DEF_CALENDAR_DATE_KIND_SUNDAY:		style = "sunday" ;		break ;	/*	日曜日(2)	*/
	case DEF_CALENDAR_DATE_KIND_HOLIDAY:	style = "holiday" ;		break ;	/*	祝祭日(3)	*/
	case DEF_CALENDAR_DATE_KIND_WEEKDAY:
	default:								style = "weekday" ;		break ;	/*	一般日(0)	*/
	}
	return( style ) ;
}




/**
 * 指定の日付が表示対象かどうかを返す。
 *
 * @return	TRUE	表示対象。
 * 			FALSE	表示対象ではない。
 */
ExtCalendar.prototype.isShowUnitValue = function ( date ) {
	return( (date>0 && date<=this.lastDate) ? TRUE : FALSE ) ;
}



/**
 * 指定の日付が有効期間内かどうかを返す。
 *
 * @return	TRUE	有効期間内。
 * 			FALSE	有効期間外。
 */
ExtCalendar.prototype.isValidyDate = function ( date ) {
	return( (date<this.validyTermStart || date>this.validyTermLast) ? FALSE : TRUE ) ;
}




/*--------------------------------------------------------
 *
 *	カレンダー表示内容を変更する場合は、
 *	以下の関数をオーバーライドすること。
 *
 *--------------------------------------------------------*/



/**
 * 一月分のカレンダを表示する。
 */
ExtCalendar.prototype.put = function () {
	document.write( this.getCalendarHtml() ) ;
}
ExtCalendar.prototype.getCalendarHtml = function ()
{
	var		msg="" ;
	var		cnt=0 ;
	var		date, day ;
	var		calendarLines =  Math.floor( (this.startDay+this.lastDate)/DEF_DATES_PER_WEEK ) ;


	if( ((this.startDay+this.lastDate) % DEF_DATES_PER_WEEK)>0 ) {
		/*	最後の週が土曜以外で終わる場合は１行追加	*/
		calendarLines ++ ;
	}


	msg += sprintf( "<table class='%s' acellspacing='0' cellpadding='0' border='0'>", this.style ) ;

	if( typeof(this.title)!="undefined" || this.title.length>0) {
		/*	タイトル表示	*/
		msg += sprintf( "<tr><th class='header' colspan='%s'>%s</th></tr>", DEF_DATES_PER_WEEK, this.title ) ;
	}

	/*	カレンダー見出し処理	*/
	msg += this.getDayHeadWord() ;

	/*	行数×一週間分の日付データを表示	*/
	for( line=0; line<calendarLines; line++ ) {
		msg += "<tr>" ;
		/*	一週間分の日付データを表示	*/
		for( dd=0; dd<DEF_DATES_PER_WEEK; dd++ ) {
			date = cnt - this.startDay + 1 ;	/*	日付換算値	*/
			day = (new Date(this.year,this.month-1,date)).getDay() ;	/*	曜日	*/
			msg += sprintf( "<td class='%s'>%s</td>",
						this.getUnitDateStyleClass( this.getUnitDateKind(date,day) ),
						this.getShowUnitValue( date )
					) ;
			cnt++ ;
		}
		msg += "</tr>" ;
	}
	msg += "</table>" ;

	return( msg ) ;
}


/**
 * カレンダの各日の表示内容を取得する。
 *
 * @param	date	日。
 */
ExtCalendar.prototype.getShowUnitValue = function ( date ) {
	/**
	 *	このインスタンスは月オブジェクトを表す。
	 *	よって、年(this.year)および月(this.month)は参照可能。
	 *	一方、日付は呼び出し側から渡される。
	 */
	return( this.isShowUnitValue(date) ? date : "&nbsp;" ) ;
}
