jiichan.com

PROGRAMMING

祝休日対応のカレンダーを作る

カレンダーもネット上ではたくさん紹介されています。
やはりjavascriptで、特にjQueryを使ったものが多いようです。また、海外のもので日本の祝休日対応がされていないものが多いと感じました。
そこでjavascriptの勉強にもなるのでjQueryを使わずに、さらに日本の祝休日対応のカレンダーを作ってみました。
このカレンダー(MkenCalendar)はこのサイトのトップページで使っています。

-----2016.03.01(修正)-----
日付データの取得用としてgetCurrentDay()メソッドを新設し、それに伴って若干の修正をしました。

-----2016.02.14(修正)-----
祝日「山の日」が増えたのでそれに対応するために修正しています。

-----2015.10.26(修正)-----
クリックした日付が分かるように、クリックした場合はその日付の背景色を変更するようにしました。
そのためプロパティとイベントのコードを追加・修正しています。

まずはカレンダーの基を準備

「javascriptにはクラスというものが無いので、関数(関数もオブジェクト)を使って他の言語のクラスの ように使う」とマニュアル本に書いていました。
まず最初にカレンダーの基になる関数MkenCalendarを作ります。


var MkenCalendar = function(tagId){
	var today = new Date();
	// カレンダーに表示される年月日
	this.nenn = today.getFullYear();
	this.tuki = today.getMonth() + 1;
	this.nichi = today.getDate();

	// 年月日の区切り文字
	this.spliter = "_";
	// 現在選択されている日付(オープン時は今日)
	this.currentDay =
		this.nenn + this.spliter + this.tuki + this.spliter + this.nichi;
	
	this.tagId = tagId;
};

カレンダーに表示される年や月に使われるプロパティnennとtukiにページオープン時の年月をセットします。
この二つのプロパティ値は、後で出てくる次月・前月ボタンをクリックすると減ったり増えたり変化する値です。
関数の引数tagIdは、このカレンダーを表示したい部分のタグのIDセレクタ名でインスタンス生成時に指定します。

プロパティやメソッドの追加(各月の日数など)

プロトタイプで関数MkenCalendarに各月の日数を追加します。2月の閏月の日数の変更はそれ専用に別のメソッドで作ってあります。


MkenCalendar.prototype = {
// 各月の日数
monthDays: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
// 前回クリックした日付の前のエレメント保持用
clickDayBeforElm: null,
// 前回クリックした日付の前の背景色保持用
clickDayBeforBackGroundColor: "#ffffff",
// クリックした日付の背景色
clickDayBackGroundColor: "#ffff99",

プロパティやメソッドの追加(今日の日付を得る)

あとあと必要になるので今日の日付を得るメソッドも追加しておきました。
書式はspliterが'_'なので yyyy_m_d のようになります。


getToday: function(){
	var today = new Date();
	// 今日の年
	var kYear = today.getFullYear();
	// 今日の月
	var kMonth = today.getMonth() + 1; 
	// 今日の日
	var kDay = today.getDate();

	return kYear + this.spliter + kMonth + this.spliter + kDay;
},

プロパティやメソッドの追加(前月・次月指定時の処理)

カレンダー前月や次月をクリックした時の年月を得るためのメソッドを追加します。


setNengetsu: function(dore){
	// 次月
	if(dore === 1){
		// ひと月プラスする
		this.tuki++;
	}
	// 前月
	if(dore === -1){
		// ひと月マイナスする
		 this.tuki--;
	}
	// 結果(月)が13ならば
	if(this.tuki === 13){
		// 年を一年プラスして
		this.nenn++;
		// 月を一月に
		this.tuki = 1;
	}
	// 結果(月)が0になったら
	if(this.tuki === 0){
		// 年を一年マイナスして
		this.nenn--;
		// 月を12月に
		this.tuki = 12;
	}
	// 閏年の場合
	if(this.isLeapYear(this.nenn))
		// 2月を29日に
		this.monthDays[1] = 29;
	else
		// その他は28日に
		this.monthDays[1] = 28;
},

プロパティやメソッドの追加(カレンダーのマスのみ作成)

カレンダーのマスのみを作成し、そのマスにclass.idをセットします。変化する年月や日付は別にセットするようにしました。
週の数は、カレンダー表示の際に日数によって上下のサイズが変わるのは嫌なので6週固定にしました。


createHTML: function(){
	// 年月の選択行を生成 =======================================
	var rowNengetsu = document.createElement("tr");	
	rowNengetsu.id = this.tagId + "NengetsuID";
	
	// 月の表示セル
	var cellYymm = document.createElement("td");
	cellYymm.id = this.tagId + "MmID";
	cellYymm.appendChild(document.createTextNode(""));
	rowNengetsu.appendChild(cellYymm);
	
	// 年の表示セル
	var cellYymm = document.createElement("td");
	cellYymm.colSpan = "4";
	cellYymm.id = this.tagId + "YyID";
	cellYymm.appendChild(document.createTextNode(""));
	rowNengetsu.appendChild(cellYymm);
	
	// 前へセル
	var cellPrev = document.createElement("td");
	cellPrev.id = this.tagId + "PrevID";
	cellPrev.appendChild(document.createTextNode("←"));
	rowNengetsu.appendChild(cellPrev);

	// 次へセル
	var cellNext = document.createElement("td");
	cellNext.id = this.tagId + "NextID";
	cellNext.appendChild(document.createTextNode("→"));
	rowNengetsu.appendChild(cellNext);
	
	// 曜日の行を生成 =========================================
	var rowWeeks = document.createElement("tr");
	rowWeeks.id = this.tagId + "WeeksID";

	// 曜日のセル
	for(var i = 0; i <= 6; i++){
		var cellWeek = document.createElement("td");
		switch (i) {
			case 0:
				cellWeek.appendChild(document.createTextNode("SUN"));
		    	break;
			case 1:
				cellWeek.appendChild(document.createTextNode("MON"));
		    	break;
			case 2:
				cellWeek.appendChild(document.createTextNode("TUE"));
		    	break;
			case 3:
				cellWeek.appendChild(document.createTextNode("WEN"));
		    	break;
			case 4:
				cellWeek.appendChild(document.createTextNode("THU"));
		    	break;
			case 5:
				cellWeek.appendChild(document.createTextNode("FRI"));
		    	break;
			case 6:
				cellWeek.appendChild(document.createTextNode("SAT"));
		    	break;
			default:
		}
		rowWeeks.appendChild(cellWeek);
	}

	var tblBody = document.createElement("tbody");
	tblBody.appendChild(rowNengetsu);
	tblBody.appendChild(rowWeeks);

	// 日付部
	// 一週間を6週(行)繰り返し
	for(var j = 0; j < 6; j++){
		var row = document.createElement("tr");
		// 1日を7日(列)繰り返し
		for(var k = 0; k <= 6; k++){
			var cell = document.createElement("td");
			var cellText = document.createTextNode("");
			cell.className = this.tagId + "DayCLS";
			cell.appendChild(cellText);
			row.appendChild(cell);
		}
		tblBody.appendChild(row);
	}

	var tbl = document.createElement("table");
	tbl.id = this.tagId + "TableID";
	tbl.appendChild(tblBody);

	document.getElementById(this.tagId).appendChild(tbl);

},

最初は要素ノードの属性の設定にsetAttributeメソッドを使いましたが、IEは他のブラウザと違いclassがclassNameとなるので ブラウザ判定の必要があり、コードも長くなるのでclassNameプロパティを使うことにしました。
class名やid名は、頭にtagIdをプラスして他のコードと重複しないようにしました。

プロパティやメソッドの追加(各マスへ年月・日付を埋め込み)

年月や矢印など、すべてのマスの数は53個で、12個目から日付になります。
表示される月のついたちの曜日(0:日曜~6:土曜)を得、1からついたちの曜日をマイナスすることで 日付マスの最初の日付を得ることができます(当然マイナスも有り得る)。
1日が0(日曜)の場合は日付マスの最初は1日となりますが、1(月曜)は0日となり、 2(火曜)の場合は日付マスの最初はマイナス1日となります。
そこで、日付がプラスになるマスのみにセットし、それ以外のマスには空白をセットし埋め込みを完成さました。


setDays: function(){
	// 月を埋め込み
	var Mm = document.getElementById(this.tagId + "MmID");
	var txtMm = document.createTextNode(this.tuki);
	Mm.replaceChild(txtMm, Mm.firstChild);
	// 年を埋め込み
	var Yy = document.getElementById(this.tagId + "YyID");
	var txtYy = document.createTextNode(this.nenn);
	Yy.replaceChild(txtYy, Yy.firstChild);

	// 日付マスの要素取得
	var CalendarTable = document.getElementById(this.tagId + "TableID");
	var tdItems = CalendarTable.getElementsByTagName("td");

	// 表示される月のついたちの曜日(0:日曜~6:土曜)
	var yobidate = new Date(this.nenn, this.tuki - 1, 1);
	var tuitati_yobi = yobidate.getDay(); 
	// 最初のマスの日付(その月の1日以前はマイナス何日となる)
	var hizuke = 1 - tuitati_yobi;

	// 閏年の場合
	if(this.isLeapYear(this.nenn))
		// 2月を29日に
		this.monthDays[1] = 29;
	else
		// その他は28日に
		this.monthDays[1] = 28;

	// 12個目のTDから日付部分のマス i=11~52
   var txtHizuke;
	for (var i = 11; i < tdItems.length; i++) {
		// 1日からその月の末日の場合は日付を表示、それ以外は空白
		if((hizuke >= 1) && (hizuke <= this.monthDays[this.tuki - 1])) {
			txtHizuke = document.createTextNode(hizuke);
		}else{
			txtHizuke = document.createTextNode("");
		}
		tdItems[i].replaceChild(txtHizuke, tdItems[i].firstChild);
		hizuke++;
	}
},

プロパティやメソッドの追加(スタイルの設定)

カレンダーの見た目は、使いかってにも影響してくるのではないかと思います。
そんなことを考えながらセットしていったら、かなりの行数になってしまいました。
CSSの別ファイルも考えましたが、javascriptの勉強なのでコード内に書き込みました。


setStyle: function(){
	// テーブル全体のスタイル ======
	// 境界線を重ねて表示
	var borderCollapseTBL = "collapse";
	// カレンダー全体の背景色
	var backgroundColorTBL = "#edeaea";
	// 全体のフォント
	var fontFamilyTBL = "Meiryo";
	// フォントの太さ
	var fontWeightTBL = "600";
	// 全体の文字表示位置(水平方向)
	var textAlignTBL = "center";
	// 全体の文字表示位置(垂直方向)
	var verticalAlignTBL = "middle";

	// 日付セルのスタイル ======
	// 日付のマス幅
	var widthCL = "28px";
	// 日付のマス高さ
	var heightCL = "23px";
	// 日付のマス内余白
	var paddingCL = "3px 9px 0px 0px";
	// 日付文字サイズ
	var fontSizeCL = "10px";
	// 日付の文字表示位置(水平方向)
	var textAlignCL = "right";
	// 日付欄のカーソル形状
	var cursorCL = "pointer";

	// マウスオーバーの場合 =====
	// マウスオーバー時のフォントサイズ
	var fontSizeOVER = "13px";

	// 今日の場合のセルスタイル =====
	// 今日の場合の背景色
	var backgroundColorTODAY = "#ffffff";

	// 曜日の文字色と背景色 =====
	// 日曜の文字色
	var colorSUN = "#FF0000";
	// 平日の文字色・当月以外の日付文字色
	var colorHEI = "#555555";
	// 土曜の文字色
	var colorSAT = "#0099FF";
	// 日曜の背景色
	var backgroundColorSUN = "#dddddd";
	// 土曜の背景色
	var backgroundColorSAT = "#dddddd";

	// 年月部のスタイル =====
	// 年月等の背景色
	var backgroundColorYM = "#f9f4f4";
	// 年月等の文字色
	var colorYM = "#555555";
	// 月の文字サイズ
	var fontSizeMM = "23px";
	// 年の文字サイズ
	var fontSizeYY = "11px";
	// 矢印の文字サイズ
	var fontSizeAL = "15px";
	// 年月等の高さ
	var heightYM = "30px";
	// 年の文字位置(水平方向)
	var textAlignYY = "left";
	// 年の文字表示位置(垂直方向)
	var verticalAlignYY = "bottom";
	// 月のマス内余白
	var paddingMM = "5px 0px 0px 0px";

	// テーブル全体 =====
	var TableTag = document.getElementById(this.tagId + "TableID");
	TableTag.style.borderCollapse = borderCollapseTBL;
	TableTag.style.backgroundColor = backgroundColorTBL;
	TableTag.style.fontFamily = fontFamilyTBL;
	TableTag.style.fontWeight = fontWeightTBL;
	TableTag.style.textAlign = textAlignTBL;
	TableTag.style.verticalAlign = verticalAlignTBL;

	// 年月部 =====
	TableTag.rows[0].style.backgroundColor = backgroundColorYM;
	TableTag.rows[0].style.color = colorYM;
	TableTag.rows[0].style.height = heightYM;
	TableTag.rows[0].cells[0].style.fontSize = fontSizeMM;
	TableTag.rows[0].cells[0].style.padding = paddingMM;
	TableTag.rows[0].cells[1].style.fontSize = fontSizeYY;
	TableTag.rows[0].cells[1].style.textAlign = textAlignYY;
	TableTag.rows[0].cells[1].style.verticalAlign = verticalAlignYY;
	TableTag.rows[0].cells[2].style.fontSize = fontSizeAL;
	TableTag.rows[0].cells[2].style.cursor = cursorCL;
	TableTag.rows[0].cells[3].style.fontSize = fontSizeAL;
	TableTag.rows[0].cells[3].style.cursor = cursorCL;
	
	// 曜日部 =====
	TableTag.rows[1].style.backgroundColor = backgroundColorYM;
	for(var i = 0; i < TableTag.rows[1].cells.length; i++){
		TableTag.rows[1].cells[i].style.width = widthCL;
		TableTag.rows[1].cells[i].style.height = heightCL;
		TableTag.rows[1].cells[i].style.fontSize = fontSizeCL;
		if(i === 0){TableTag.rows[1].cells[i].style.color = colorSUN;}
		if((i >= 1) && (i <= 5)){
			TableTag.rows[1].cells[i].style.color = colorHEI;
		}
		if(i === 6){TableTag.rows[1].cells[i].style.color = colorSAT;}
	}

	// 日付セル部 =====
	for(var j = 2; j < TableTag.rows.length; j++){
		var row = TableTag.rows[j];
		for(var i = 0; i < row.cells.length; i++){
			var cell = row.cells[i];
			cell.style.width = widthCL;
			cell.style.height = heightCL;
			cell.style.padding = paddingCL;
			cell.style.textAlign = textAlignCL;
			cell.style.fontSize = fontSizeCL;
			cell.style.cursor = cursorCL;

			// 曜日ごとの文字色
			if(i === 0){
				cell.style.color = colorSUN;
				cell.style.backgroundColor = backgroundColorSUN;
			}
			
			if(i === 6){
				cell.style.color = colorSAT;
				cell.style.backgroundColor = backgroundColorSAT;
			}
			// 祝日の場合
			var syukuNo =
				this.holiday(this.nenn, this.tuki, cell.firstChild.nodeValue);
			if(syukuNo >= 0){
				cell.style.color = colorSUN;
			}
			// 今日の場合背景色を変更
			var checkDay =
				this.nenn + this.spliter 
				+ this.tuki + this.spliter 
				+ cell.firstChild.nodeValue;
			if(checkDay === this.getToday()){
				cell.style.backgroundColor = backgroundColorTODAY;
			}else{
				if(i === 0){cell.style.backgroundColor = backgroundColorSUN;}
				if((i >= 1) && (i <= 5)){
					cell.style.backgroundColor = backgroundColorTBL;}
				if(i === 6){cell.style.backgroundColor = backgroundColorSAT;}
			}
			// クリックされた日の場合は背景色を変更
			if(checkDay === this.currentDay){
				cell.style.backgroundColor = this.clickDayBackGroundColor;
				this.clickDayBeforElm = cell;
			}
			// 日付部分のマウスオーバー・マウスアウト(文字のサイズとカーソル形状)
			if(cell.firstChild.nodeValue.length > 0){
				cell.onmouseover = function(){
					this.style.fontSize = fontSizeOVER;
				};
			}else{
				// 日付の無いセルのカーソル
				cell.onmouseover = function(){this.style.cursor = "default";};
			}
			cell.onmouseout = function(){
				this.style.fontSize = fontSizeCL;
			};
		}
	}
},

プロパティやメソッドの追加(イベントの設定)

イベントは「前月クリック」と「次月クリック」それに「日付クリック」です。
クリックされた日付はプロパティclickDayに入ります。


setEvent: function(){
	// イベントのthisはインスタンスではなくイベントの発生元を指すので
	// インスタンスは一旦ローカル変数に代入して使用する
	var self = this;	

	// 前月をクリック
	this.addListener(document.getElementById(this.tagId + 'PrevID'),
		'click', function(){
			self.setNengetsu(-1);
			self.setDays();
			self.setStyle();
	});
	
	// 次月をクリック
	this.addListener(document.getElementById(this.tagId + 'NextID'),
		'click', function(){
			self.setNengetsu(1);
			self.setDays();
			self.setStyle();
	});

	// 日付をクリック
	var elements =
		document.getElementsByClassName(self.tagId + "DayCLS");
	for (var i = 0; i < elements.length; i++) {
		this.addListener(elements[i], 'click', 
			function(){
				var mm = self.tuki;
				var dd = this.firstChild.nodeValue;
				if (dd) {	// 日付のあるものだけ
					self.currentDay =
						self.nenn + self.spliter
						+ mm + self.spliter + dd;

					// クリックした日付の背景色を変える
					if(self.clickDayBeforElm === null){
						self.clickDayBeforBackGroundColor =
							this.style.backgroundColor;
						// クリックした日付の背景色を変える
						this.style.backgroundColor =
							self.clickDayBackGroundColor;
						self.clickDayBeforElm = this;
					}else{
						if(this.style.backgroundColor!==self.clickDayBackGroundColor){
							// 前回クリックした日付の背景色を元の色に戻す
							self.clickDayBeforElm.style.backgroundColor =
									self.clickDayBeforBackGroundColor;
							self.clickDayBeforBackGroundColor =
									this.style.backgroundColor;
							// クリックした日付の背景色を変える
							this.style.backgroundColor =
									self.clickDayBackGroundColor;
							self.clickDayBeforElm = this;
						}
					}
				}else{
					return;
				}
			}
		);
	}
},

上記のイベント登録用関数。


MkenCalendar.prototype.addListener = function(elm, ev, listener) {
	if(elm.addEventListener) {		// IE以外
		elm.addEventListener(ev, listener, false);
	} else if(elm.attachEvent) {	// IE
		elm.attachEvent('on' + ev, listener);
	} else {
		throw new Error('イベントリスナーに未対応です。');
	}
};

プロパティやメソッドの追加(祝休日の判定)

祝休日のメソッドは以下のとおりで、戻り値として配列のインデックスを返すようにしました。
祝休日でない場合の戻り値は-1となります。


holiday: function(toshi, tsuki, hi){
	var syukujitsu = [];
	var syuku_cnt = 0;
	var nichi;
	var syukuDay;

	// その年の祝日を計算
	// 元日(1月1日)
	syukujitsu[0] = toshi + this.spliter + "1" + this.spliter + "1";
	// 建国記念日(2月11日)
	syukujitsu[1] = toshi + this.spliter + "2" + this.spliter + "11";
	// 昭和の日(4月29日)
	syukujitsu[2] = toshi + this.spliter + "4" + this.spliter + "29";
	// 憲法記念日(5月3日)
	syukujitsu[3] = toshi + this.spliter + "5" + this.spliter + "3";
	// みどりの日(5月4日)
	syukujitsu[4] = toshi + this.spliter + "5" + this.spliter + "4";
	// こどもの日(5月5日)
	syukujitsu[5] = toshi + this.spliter + "5" + this.spliter + "5";
	// 山の日(8月11日)
	syukujitsu[6] = toshi + this.spliter + "8" + this.spliter + "11";
	// 文化の日(11月3日)
	syukujitsu[7] = toshi + this.spliter + "11" + this.spliter + "3";
	// 勤労感謝の日(11月23日)
	syukujitsu[8] = toshi + this.spliter + "11" + this.spliter + "23";
	// 天皇誕生日(12月23日)
	syukujitsu[9] = toshi + this.spliter + "12" + this.spliter + "23";
	// 成人の日(1月の2月曜日)
	nichi = this.howDay(toshi, 1, 2, 1);
	syukujitsu[10] = toshi + this.spliter + "1" + this.spliter + nichi;
	// 海の日(7月第3月曜日)
	nichi = this.howDay(toshi, 7, 3, 1);
	syukujitsu[11] = toshi + this.spliter + "7" + this.spliter + nichi;
	// 敬老の日(9月第3月曜日)
	nichi = this.howDay(toshi, 9, 3, 1);
	syukujitsu[12] = toshi + this.spliter + "9" + this.spliter + nichi;
	// 体育の日(10月第2月曜日)
	nichi = this.howDay(toshi, 10, 2, 1);
	syukujitsu[13] = toshi + this.spliter + "10" + this.spliter + nichi;
	// 春分の日(前年の2月1日官報に掲載)・簡易計算法
	var haru =
		Math.floor(20.8431+0.242194*(toshi-1980)-Math.floor((toshi-1980)/4));
	syukujitsu[14] = toshi + this.spliter + "3" + this.spliter + haru;
	// 秋分の日(前年の2月1日官報に掲載)・簡易計算法
	var aki =
		Math.floor(23.2488+0.242194*(toshi-1980)-Math.floor((toshi-1980)/4));
	syukujitsu[15] = toshi + this.spliter + "9" + this.spliter + aki;

	// 振替休日
	// 元日(1月1日)
	syukuDay = new Date(toshi, 0, 1);
	if (syukuDay.getDay() === 0) {
		syukujitsu[16] = toshi + this.spliter + "1" + this.spliter + "2";
	}
	// 建国記念日(2月11日)
	syukuDay = new Date(toshi, 1, 11);
	if (syukuDay.getDay() === 0) {
		syukujitsu[17] = toshi + this.spliter + "2" + this.spliter + "12";
	}
	// 昭和の日(4月29日)
	syukuDay = new Date(toshi, 3, 29);
	if (syukuDay.getDay() === 0) {
		syukujitsu[18] = toshi + this.spliter + "4" + this.spliter + "30";
	}
	// 憲法記念日(5月3日)
	syukuDay = new Date(toshi, 4, 3);
	if (syukuDay.getDay() === 0) {
		syukujitsu[19] = toshi + this.spliter + "5" + this.spliter + "6";
	}
	// みどりの日(5月4日)
	syukuDay = new Date(toshi, 4, 4);
	if (syukuDay.getDay() === 0) {
		syukujitsu[20] = toshi + this.spliter + "5" + this.spliter + "6";
	}
	// こどもの日(5月5日)
	syukuDay = new Date(toshi, 4, 5);
	if (syukuDay.getDay() === 0) {
		syukujitsu[21] = toshi + this.spliter + "5" + this.spliter + "6";
	}
	// 山の日(8月11日)
	syukuDay = new Date(toshi, 7, 11);
	if (syukuDay.getDay() === 0) {
		syukujitsu[22] = toshi + this.spliter + "8" + this.spliter + "12";
	}
	// 文化の日(11月3日)
	syukuDay = new Date(toshi, 10, 3);
	if (syukuDay.getDay() === 0) {
		syukujitsu[23] = toshi + this.spliter + "11" + this.spliter + "4";
	}
	// 勤労感謝の日(11月23日)
	syukuDay = new Date(toshi, 10, 23);
	if (syukuDay.getDay() === 0) {
		syukujitsu[24] = toshi + this.spliter + "11" + this.spliter + "24";
	}
	// 天皇誕生日(12月23日)
	syukuDay = new Date(toshi, 11, 23);
	if (syukuDay.getDay() === 0) {
		syukujitsu[25] = toshi + this.spliter + "12" + this.spliter + "24";
	}
	// 春分の日
	syukuDay = new Date(toshi, 2, haru);
	if (syukuDay.getDay() === 0) {
		var haruDay = parseInt(haru) + 1;
		syukujitsu[26] = toshi + this.spliter + "11" + this.spliter + haruDay;
	}
	// 秋分の日
	syukuDay = new Date(toshi, 8, aki);
	if (syukuDay.getDay() === 0) {
		var akiDay = parseInt(aki) + 1;
		syukujitsu[27] = toshi + this.spliter + "9" + this.spliter + akiDay;
	}

	// 国民の休日(敬老の日と秋分の日に挟まれた日)
	var keiro = parseInt(syukujitsu[12].substr(7, 2));
	var syubun = parseInt(syukujitsu[15].substr(7, 2));
	if (syubun - keiro === 2) {
		keiro++;
		syukujitsu[28] = toshi + this.spliter + "9" + this.spliter + keiro;
	}

	// 指定の日が祝日かを判定
	for (var j = 0; j <= 28; j++) {
		syuku_cnt =
			syukujitsu.indexOf(toshi + this.spliter + tsuki + this.spliter + hi);
	}
	// 祝日の配列インデックスを返す -1は祝日でない
	return syuku_cnt;
},

また、祝休日には第n番目の曜日となる場合もあるので、「第n番目の曜日の日付を求める」メソッドも追加しました。


howDay: function(year, month, n, WantDayWeek){
	var nichi;
	var FirstDay = new Date(year, month-1, 1);

	var FirstDayWeek = FirstDay.getDay();	// 1日の曜日
	if ((WantDayWeek - FirstDayWeek) >= 0) {
		// 求めたい日付(0かプラスの場合)
		nichi = 1 + (WantDayWeek - FirstDayWeek) + 7 * (n - 1);
	}
	if ((WantDayWeek - FirstDayWeek) < 0) {
		// 求めたい日付(マイナスの場合)
		nichi = 1 + (WantDayWeek - FirstDayWeek) + (7 * n);
	}
	return nichi;
},

プロパティやメソッドの追加(閏年の判定)

上の項で使用された閏年を得るメソッドは次のとおり。


isLeapYear: function(year){
	if(((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) {
		return true;
	} else {
		return false;
	}
},

プロパティやメソッドの追加(選択されている日付を得るメソッド)

現在選択されている日付を得るメソッドです。
引数が1のときは月日が一桁表示、それ以外は二桁表示の日付が返されます。


getCurrentDay: function(fm) {
	if(fm === 1) {	// 一桁表示
		return this.currentDay;
	} else {			// それ以外は二桁表示
		var yymmdd = this.currentDay.split(this.spliter);
		// yymmdd[0]	年
		// yymmdd[1]	月の一桁表示
		// yymmdd[2]	日の一桁表示
		if (yymmdd[1] < 10) {yymmdd[1] = '0' + yymmdd[1];}
		if (yymmdd[2] < 10) {yymmdd[2] = '0' + yymmdd[2];}
		return yymmdd[0] + this.spliter + yymmdd[1] + this.spliter + yymmdd[2];
	}
},

プロパティやメソッドの追加(最後はカレンダーを表示するメソッド)

MkenCalendarのインスタンスを得て、このメソッドを呼び出すことでカレンダー表示されます。


showCalendar: function(){
	this.createHTML();	// calendar枠作成と各マスのid.classをセット
	this.setDays();		// 日付の埋め込み
	this.setEvent();		// イベントをセット
	this.setStyle();		// スタイルをセット
}

簡単な使い方

簡単な使い方は次のとおり。HTML内のカレンダーを表示したいところにブロックレベル要素 (この例ではidがcalendar1)を置きます。


<div id="calendar1"></div><

#calendar1 {
	width: 259px;		/* カレンダー本体のサイズ */
	height: 209px;		/* カレンダー本体のサイズ */
	padding: 10px;
	margin: 20px auto 0 50px;
	background-color: #aaaaaa;
}

そしてカレンダーを操作するjavascript(jQueryを使用している)で (1) インスタンスを作成し (2) showCalendarで表示 (3) 日付クリックイベントを記述 することになります。


var tagStr = "calendar1";
// カレンダーのインスタンス(1)
var cal = new MkenCalendar(tagStr);

// カレンダーの表示(2)
cal.showCalendar();

alert("今日は" + cal.getCurrentDay() + " です");	// 二桁表示

// カレンダーの日付クリックイベント(3)
$("." + tagStr + "DayCLS").on("click", function(){
	alert(cal.getCurrentDay(1) + " がクリックされました");	// 一桁表示
});

カレンダーを表示した直後は今日の年月日がプロパティに入っています。