Calendar Control: Calendar inside a Container

このExampleのページ(上のリンク)にこう書いてある。

The default Calendar/CalendarGroup controls do not provide positioning or dragdrop support natively, as the Container family's Overlay control and its subclasses do.(YUIのExampleのページより引用)
デフォルトのCalendarやCalendarGroupは、位置決めやドラッグ・アンド・ドロップの機能をもってないが、OverlayやそのサブクラスといったContainerは、それをもっている。

そのために、CalendarをOverlay(のサブクラスPanel)のサブクラスであるDialogに仕込ませる。
というのが、Exampleの目的である。
Calendarについては、以前のExample「Button Control: Simple Calendar Menu Button」でボタンに仕込んだが、今回のようにPanelの仲間に忍ばせるというのも一般的な使い方だろう。

この忍ばせ方が(ボタンのときと違って)いたって簡単で、(添付のソースコードを見てもらうのが手っ取り早いが)Markupに忍ばせて、ここからDialogとCalendarを生成してしまう。

今回のサンプルでは、YUIのサンプルに手を加えて、カレンダーの表示を日本語に変えてみた。(下の図)
これには、CalendarのConfiguration Attributesを変えてやればよい。
YUI.widget.CalendarのAPIドキュメントへのリンク

月には「Jan,Feb …」の代わりに「睦月,如月…」が表示され、曜日の所は「日,月…」と表示される。
カレンダーから日にちを選んで、Selectボタンを押すと、以下のようになる。

以下に、Javascriptを含む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/container/assets/skins/sam/container.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/dragdrop/dragdrop-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> 
<script type="text/javascript" src="scripts/yui/container/container-min.js"></script> 
<script type="text/javascript" src="scripts/yui/calendar/calendar-min.js"></script> 

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

/* 最初はつぶしておく */
.container {
	height:0;
}

    /* Clear calendar's float */
#container .bd:after {
	content:".";
	display:block;
	clear:left;
	height:0;
	visibility:hidden;
}
 
/* Have calendar squeeze upto bd bounding box */
#container .bd {
	padding:0;
}
 
/* Remove calendar's border and set padding in ems instead of px, so we can specify an width in ems for the container */
#cal {
	border:none;
	padding:1em
}
 
/* Datefield look/feel */
.datefield {
    position:relative;
    top:10px;
    left:10px;
    white-space:nowrap;
    border:1px solid black;
    background-color:#eee;
    width:25em;
    padding:5px;
}
 
.datefield input,
.datefield button,
.datefield label  {
	vertical-align:middle
}
 
.datefield label  {
	font-weight:bold
}
.datefield input  {
	width:15em
}
.datefield button  {
	padding:0 5px 0 5px; 
	margin-left:2px;
}
.datefield button img {
	padding:0;
	margin:0;
	vertical-align:middle
}
 
/* Example box
    .box {
	position:relative;
	height:30em;
    }
 */
 
</style>

<script type="text/javascript">
YAHOO.namespace("EGP");

YAHOO.EGP.DialogCalendar = function() {
    var dialog, calendar;
    var Dom	=YAHOO.util.Dom;
    var Event=YAHOO.util.Event;

    var okHandler = function () {
        if (calendar.getSelectedDates().length > 0) {

            var selDate = calendar.getSelectedDates()[0];

            // Pretty Date Output, using Calendar's Locale values: Friday, 8 February 2008
            var wStr = calendar.cfg.getProperty("WEEKDAYS_LONG")[selDate.getDay()];
            var dStr = selDate.getDate();
            var mStr = calendar.cfg.getProperty("MONTHS_LONG")[selDate.getMonth()];
            var yStr = selDate.getFullYear();

            Dom.get("date").value = yStr + "年, " + mStr + " " + dStr + "日 " + wStr;
//            Dom.get("date").value = wStr + ", " + dStr + " " + mStr + " " + yStr;
        } else {
            Dom.get("date").value = "";
        }
        this.hide();
    }

    var cancelHandler = function () {
        this.hide();
    }
    			
	return{
    	init: function() {

        calendar = new YAHOO.widget.Calendar("cal", {
            iframe:false,          // Turn iframe off, since container has iframe support.
            hide_blank_weeks:true  // Enable, to demonstrate how we handle changing height, using changeContent
        });
 
        dialog = new YAHOO.widget.Dialog("container", {
            context:["show", "tl", "bl"],
            buttons:[ {text:"Select", 
                		isDefault:true, 
                		handler: okHandler}, 
                      {text:"Cancel", 
         				handler: cancelHandler}],
            // Sam Skin dialog needs to have a width defined (7*2em + 2*1em = 16em).
            width:"16em",  
            draggable:false,
            close:true
        });
        
        calendar.cfg.setProperty("MONTHS_LONG",["睦月","如月","弥生","卯月","皐月","水無月","文月","葉月","長月","神無月","霜月","師走",]);
        calendar.cfg.setProperty("MONTHS_SHORT",["睦","如","弥","卯","皐","水","文","葉","長","神","霜","師",]);
        calendar.cfg.setProperty("WEEKDAYS_LONG",["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"]);
        calendar.cfg.setProperty("WEEKDAYS_SHORT",["日","月","火","水","木","金","土"]);
        calendar.render();
        dialog.render();
 
        // Using dialog.hide() instead of visible:false is a workaround for an IE6/7 container known issue with border-collapse:collapse.
        dialog.hide();
 
        calendar.renderEvent.subscribe(function() {
            // Tell Dialog it's contents have changed, Currently used by container for IE6/Safari2 to sync underlay size
            dialog.fireEvent("changeContent");
        });
 
        Event.on("show", "click", function() {
			dialog.show();
			if (YAHOO.env.ua.opera && document.documentElement) {
				// Opera needs to force a repaint
				document.documentElement.className += "";
			} 
		});
    	
		}
	};
}();
		
//DOMが完全にloadされたら、サンプルを初期化する。
YAHOO.util.Event.onDOMReady(
		//DomReadyイベントで発火するハンドラ
		YAHOO.EGP.DialogCalendar.init,
		//ハンドラに渡すオブジェクト(関数)
		YAHOO.EGP.DialogCalendar,
		//ハンドラは、上記のオブジェクトのスコープをもつ。   
		true
);
</script>
</HEAD>

<BODY class="yui-skin-sam">
<div id="main">
<p>
DialogにCalendarを仕込むサンプルです。
</p>
<div class="box"> 
	<!-- 入力フィールド -->
   <div class="datefield"> 
      <label for="date">Date: </label>
      	<input type="text" id="date" name="date" value="" />
      	<button type="button" id="show" title="Show Calendar">
      		<img src="http://developer.yahoo.com/yui/examples/calendar/assets/calbtn.gif" width="18" height="18" alt="Calendar" >
      	</button> 
   </div>
   <!-- MarkupでDialogとカレンダーの位置を決めてしまう -->
   <!-- container: Dialog用のmarkup --> 
   <div id="container"> 
      <div class="hd">Calendar</div> 
      <div class="bd"> 
		   <!-- cal: Calendar用のmarkup --> 
         <div id="cal"></div> 
      </div> 
   </div> 
</div>

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