日付選択のプルダウンに対してjQuery Uに含まれるdatepickerを使う方法をメモついでに紹介。
CakePHP 1.2.6 + jQuery 1.3.2 + jQuery UI 1.7.2で確認。
Formヘルパーでは、タイムスタンプ系のフィールドを持つカラムに対してinput()
を使ったり、date()
やdateTime()
といったメソッドでプルダウンによる日付選択を表示させるのはごく一般的だと思いますが、これを発展させてカレンダーから日付を選択することもできるように簡単に機能を追加する方法をご紹介します。
jQueryに含まれるdatepickerは便利な機能でして、オプション次第でいろいろな表示ができます。しかし、このカレンダーはinput
に対してしか発動させられません。よって今回のようなプルダウン(selectタグ)には直接結びつけることはできないのです。そこで下記のようなJavaScriptコードを用意して対応してみました。これで一応YMD以外の形式でも大丈夫だと思うのですが。。。
$(function(){
var $date_input = '<input type="hidden" class="datepicker" value="" />';
$('.form div.input.date').append($date_input);// 日付のみの場合(date)
$('.form div.input.datetime').find('select:eq(2)').after($date_input);// 日時も含まれる場合(dateTime)
$('input.datepicker').datepicker({
showOn:'button',
buttonText:'<span class="datepicker-icon"></span>',
changeMonth: true,
changeYear: true,
showMonthAfterYear: true,
monthNamesShort: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
dayNamesMin: ['日','月','火','水','木','金','土'],
beforeShow: function(){
var date = new Date(
$(this).prevAll("select[id$='Year']:first").val(),
$(this).prevAll("select[id$='Month']:first").val()-1,
$(this).prevAll("select[id$='Day']:first").val()
);
$(this).datepicker('setDate', date);
},
onClose: function(){
var date = $(this).datepicker('getDate');
var day = ('0' + (date.getDate()+1)).slice(-2);
var month = ('0' + (date.getMonth()+1)).slice(-2);
$(this)
.prevAll("select[id$='Year']:first").val(date.getFullYear()).end()
.prevAll("select[id$='Month']:first").val(month).end()
.prevAll("select[id$='Day']:first").val(day);
}
});
});
最初の3行ではもともと存在しないinputタグを日付選択プルダウンの後に隠し要素として配置しています。これにはdatepicker
というクラスを付与しておきます。
次にdatepicker
のクラスが付与されたinput
、すなわち事前に用意した隠しinput
に対してdatepicker
を発動させます。
このままではプルダウンとの結びつきが無いので、オプションで要となるコールバック関数(無名関数)を仕込みます。ひとつはカレンダー表示時にプルダウンからDate
オブジェクトを作成して読み込ませるもの。もうひとつはカレンダーを閉じたときに選択されている日付をプルダウンに反映させるもの。それぞれbeforeShow
とonClose
オプションで定義しています。
結局最初に用意した隠しinput
はただの足掛かり的存在であり、データのやり取りには関わりません。
それ以外のdatepicker
オプションはお好みによりますが、ボタンにはspan
タグを設定して、CSSでブロック表示し背景にアイコン画像を設定しています。これはちょっとしたテクニックですが、ボタンのアイコン画像をCSSで指定しているので、ページのパスがどこであろうと、ソースに変更無く同じアイコンを表示させることを可能としています。
なおDate
オブジェクトの扱いでは月の数に対して+1
したり-1
したりするのは忘れてはいけませんね。
ちなみにonClose
では下記のコードが含まれています。
var month = ('0' + (date.getMonth()+1)).slice(-2);
これはいわゆる数値のゼロ埋め表記。フォーマット関数に例えると%02d
を指定しているような動作をします。Form
ヘルパーで生成された月プルダウンのvalue
値はゼロ埋めの2桁の数なので、この作業が必要となります。
わりとあっさりできましたが手軽なので重宝すると思いますよ。
コメント