Button Control: Calendar Menu Button with Date on Button Face

このExampleも先の「Button Control: Simple Calendar Menu Button」と殆ど同じ内容のカレンダーピッカー。

唯一の違いは、これがForm送信を意識していることで、ピックアップした日付はhiddenのフィールド(select+opetionの月日と、テキストフィールドの年)に格納されるとともに、ボタンラベルとなる。

初期画面は以下。

ここで「Choose A Date」ボタンを押すと、カレンダーが現れる。

カレンダーで日付を選択すると、ラベルが変更となり、カレンダーピッカーは隠れる。

以下にmodule patternで書き直した、htmlの全文を示す。
カレンダーの作成、表示、選択といった流れは、「先の例」とまったく同じである。
以下のサンプルでは、window.loadの代わりに、以下のROMReadyによって処理を開始している。(以下のhtmlのように)大きいmarkup(id=datefields)のある場合には、かならずこのような配慮が必要である。

//DOMが完全にloadされたら、サンプルを初期化する。
YAHOO.util.Event.onDOMReady(
	//DomReadyイベントで発火するハンドラ
	YAHOO.EGP.CalendarButton.init,
	//ハンドラに渡すオブジェクト(関数)
	YAHOO.EGP.CalendarButton,
	//ハンドラは、上記のオブジェクトのスコープをもつ。   
	true
);

>|html|
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>Ajax_Sampling</TITLE>
<style type="text/css">
body {
	margin:0;
	padding:0;
}
</style>
<link rel="stylesheet" type="text/css" href="scripts/yui/fonts/fonts-min.css" />
<link rel="stylesheet" type="text/css" href="scripts/yui/button/assets/skins/sam/button.css" />
<link rel="stylesheet" type="text/css" href="scripts/yui/calendar/assets/skins/sam/calendar.css" />
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="scripts/yui/container/container_core-min.js"></script>
<script type="text/javascript" src="scripts/yui/calendar/calendar-min.js"></script>
<script type="text/javascript" src="scripts/yui/element/element-beta-min.js"></script>
<script type="text/javascript" src="scripts/yui/button/button-min.js"></script>

<style type="text/css" id="defaultstyle">
#container {
	margin: 2px;
	padding: 3px;
	width: 500px;
/*	height: auto; */
	border:1px dashed #999999;
}

    /*
        Set the "zoom" property to "normal" since it is set to "1" by the 
        ".example-container .bd" rule in yui.css and this causes a Menu
        instance's width to expand to 100% of the browser viewport.
    */
    
div.yuimenu .bd {
	zoom: normal;
}

#calendarmenu {
	position: absolute;
}

/*
    Restore default padding of 10px for the calendar containtainer 
    that is overridden by the ".example-container .bd .bd" rule 
    in yui.css.
*/

#calendarcontainer {
	padding:10px;
}
    
#personalinfo {
	border: solid 1px #666;
	padding: .5em;
}

#calendarpicker  {
	vertical-align: baseline;
}

div.field {
	padding: .25em;
}

input#year {
	width: 4em;
}
</style>

<script type="text/javascript">
//
//モジュールパターンで実装する。
//
YAHOO.namespace("EGP");

YAHOO.EGP.CalendarButton = function() {

	var Event = YAHOO.util.Event;
	var Dom = YAHOO.util.Dom;
	var oCalendarMenu;
	var oButton;

	// カレンダー表示ボタンクリック時のハンドラー
	var onButtonClick = function () {

		// OVerlayインスタンスのボディー部にid=buttoncalendarでカレンダーインスタンス
		// を作る。
		// (※)カレンダーインスタンスは1回しか作成されない。
		var oCalendar = new YAHOO.widget.Calendar("buttoncalendar", 
				oCalendarMenu.body.id);

		// カレンダーのselectイベントに、markupとボタンへの日付の編集と、カレンダーの非表示を
		// sbscribeする。
		oCalendar.selectEvent.subscribe(function (p_sType, p_aArgs) {
			var aDate,
				nMonth,
				nDay,
				nYear;
			var wkStr;
			
			if (p_aArgs) {
			//ラベルの編集
				aDate = p_aArgs[0][0];
				nMonth = aDate[1];
				nDay = aDate[2];
				nYear = aDate[0];
				wkStr = nYear + "/" + nMonth + "/" + nDay;
								
				oButton.set("label", wkStr);

				// 隠しフィールドの編集
				Dom.get("month").selectedIndex = (nMonth - 1);
				Dom.get("day").selectedIndex = (nDay - 1);
				Dom.get("year").value = nYear;
			}else{
				wkStr="date unknown";
			}
			oCalendarMenu.hide();
		});

		// Calendar表示時の処理
		// 本日をフォーカスさせ、ページを送ったら先頭日にフォーカスを当てる(点線の枠)。
		oCalendar.renderEvent.subscribe(focusDay, oCalendar, true);

		// Calendarのレンダリング
		oCalendar.render();
		
		// Buttonのクリックは1回だけなので、unsubscribeする。
		// この後のボタンクリックは、ボタンインスタンスを再表示してMenu処理をするだけ。
		// (これは、oButton生成時に設定される)
		this.unsubscribe("click", onButtonClick);
	};

	// 日にちにfocusを当てるための関数。
	var focusDay = function () {

		// Calelndarインスタンスを生成したDOM(id="buttoncalendar")から
		// Table Bodyをとってくる。http://www.howtocreate.co.uk/tutorials/javascript/domtables
		var oCalendarTBody = Dom.get("buttoncalendar").tBodies[0],
			// カレンダーの全ての日を取ってくる(aタグで書かれている)。
			aElements = oCalendarTBody.getElementsByTagName("a"),
			oAnchor;

		if (aElements.length > 0) {
			// Dom.batch(Array,fn)は、Array要素に対して、繰り返しfnを適用する。
			Dom.batch(aElements, function (element) {
				// elementの親ノードが"today"というclassをもてば、アンカー
				// をそのエレメントに貼る。
				// この場合は、td要素。
				if (Dom.hasClass(element.parentNode, "today")) {
					oAnchor = element;
				}
			});

			// アンカーが貼られなかったら、先頭日に貼る。(月が送られたときの処理)
			if (!oAnchor) {
				oAnchor = aElements[0];
			}

			// 0msec後にoAnchorにたいして、functionを実行。
			YAHOO.lang.later(0, oAnchor, function () {
				try {
					oAnchor.focus();
				}
				catch(e) {}
			});
			
		}
	};
		
	return{
    	init: function() {

		// Calendarインスタンスを入れるOverlayインスタンスの作成。
		// id=calendarmenuとする。
			oCalendarMenu = new YAHOO.widget.Overlay("calendarmenu", 
								{ visible: false });

			// 年月日を隠しフィールドの取得
			var oDateFields = Dom.get("datefields");
			oMonthField = Dom.get("month"),
			oDayField = Dom.get("day"),
			oYearField = Dom.get("year");

			// 年月日を隠しフィールドにする
			oMonthField.style.display = "none";
			oDayField.style.display = "none";
			oYearField.style.display = "none";

			// ボタンの作成
			oButton = new YAHOO.widget.Button({ 
							type: "menu", 
							id: "calendarpicker", 
							label: "Choose A Date", 
							menu: oCalendarMenu, 
							container: "datefields" });

			// ボタンのappendToイベントに対して、Calendarインスタンスを入れるための
			// 空のbodyをセットする。
			// このbodyのidをcalendarcontainerとする。
			oButton.on("appendTo", function () {
				oCalendarMenu.setBody("&#32;");
				oCalendarMenu.body.id = "calendarcontainer";
			});

			// ボタンのクリックイベントのハンドラとして、onButtonClickを設定する。
			oButton.on("click", onButtonClick);

			// oCalendarMenu上でkeyが押され、それがesc keyの場合、フォーカスを
			// ボタンに返す。
			Event.on(oCalendarMenu.element, "keydown", 
				function (p_oEvent) {
					if (Event.getCharCode(p_oEvent) === 27) {
						oCalendarMenu.hide();
						oButton.focus();
					}
				}, 
			null, 
			oButton
			);
		}
	};
}();

//DOMが完全にloadされたら、サンプルを初期化する。
YAHOO.util.Event.onDOMReady(
	//DomReadyイベントで発火するハンドラ
	YAHOO.EGP.CalendarButton.init,
	//ハンドラに渡すオブジェクト(関数)
	YAHOO.EGP.CalendarButton,
	//ハンドラは、上記のオブジェクトのスコープをもつ。   
	true
);

</script>
</HEAD>

<BODY class="yui-skin-sam">
<div id="container">
<p>
Calendar Buttonの作り方のサンプルです。
</p>
<form id="button-example-form" name="button-example-form" method="post">

    <fieldset id="personalinfo">

		<legend>Personal Information</legend>

		<div class="field">
	        <label for="firstname">First Name: </label>
	        <input type="text" id="firstname" name="firstname" value="">
        </div>

		<div class="field">
	        <label for="lastname">Last Name: </label>
	        <input type="text" id="lastname" name="lastname" value="">
        </div>

		<div class="field" id="datefields">

	        <label for="month">Birthday: </label>

	        <select id="month" name="month">
	        	<option value="01">01</option>
	        	<option value="02">02</option>
	        	<option value="03">03</option>
	        	<option value="04">04</option>
	        	<option value="05">05</option>

	        	<option value="06">06</option>
	        	<option value="07">07</option>
	        	<option value="08">08</option>
	        	<option value="09">09</option>
	        	<option value="10">10</option>
	        	<option value="11">11</option>

	        	<option value="12">12</option>
	        </select>

	        <select id="day" name="day">
	        	<option value="01">01</option>
	        	<option value="02">02</option>
	        	<option value="03">03</option>

	        	<option value="04">04</option>
	        	<option value="05">05</option>
	        	<option value="06">06</option>
	        	<option value="07">07</option>
	        	<option value="08">08</option>
	        	<option value="09">09</option>

	        	<option value="10">10</option>
	        	<option value="11">11</option>
	        	<option value="12">12</option>
	        	<option value="13">13</option>
	        	<option value="14">14</option>
	        	<option value="15">15</option>

	        	<option value="16">16</option>
	        	<option value="17">17</option>
	        	<option value="18">18</option>
	        	<option value="19">19</option>
	        	<option value="20">20</option>
	        	<option value="21">21</option>

	        	<option value="22">22</option>
	        	<option value="23">23</option>
	        	<option value="24">24</option>
	        	<option value="25">25</option>
	        	<option value="26">26</option>
	        	<option value="27">27</option>

	        	<option value="28">28</option>
	        	<option value="29">29</option>
	        	<option value="30">30</option>
	        	<option value="31">31</option>
	        </select>

			<input type="text" id="year" name="year" value="">

		</div>

		<div class="field">

			<input type="submit" id="submit-button" name="submit-button" value="Submit Form">

		</div>

    </fieldset>

</form>

</div>
</BODY>		
</HTML>