[CakePHP] FormヘルパーとjQuery UIのdatepickterを連動させる

  • このエントリーをはてなブックマークに追加

日付選択のプルダウンに対して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オブジェクトを作成して読み込ませるもの。もうひとつはカレンダーを閉じたときに選択されている日付をプルダウンに反映させるもの。それぞれbeforeShowonCloseオプションで定義しています。
結局最初に用意した隠しinputはただの足掛かり的存在であり、データのやり取りには関わりません。

それ以外のdatepickerオプションはお好みによりますが、ボタンにはspanタグを設定して、CSSでブロック表示し背景にアイコン画像を設定しています。これはちょっとしたテクニックですが、ボタンのアイコン画像をCSSで指定しているので、ページのパスがどこであろうと、ソースに変更無く同じアイコンを表示させることを可能としています。

なおDateオブジェクトの扱いでは月の数に対して+1したり-1したりするのは忘れてはいけませんね。
ちなみにonCloseでは下記のコードが含まれています。

var month = ('0' + (date.getMonth()+1)).slice(-2);

これはいわゆる数値のゼロ埋め表記。フォーマット関数に例えると%02dを指定しているような動作をします。Formヘルパーで生成された月プルダウンのvalue値はゼロ埋めの2桁の数なので、この作業が必要となります。

わりとあっさりできましたが手軽なので重宝すると思いますよ。

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。




コメントを残す