thinking now...

旅とライブと祭と廃墟。

jQueryUIのDatepickerで複数の日付を選択する(簡易版)

   

タイトルには簡易版って書きましたけど、どっちかといえば安易版?w
ユーザー側で使うのは重いんで、管理画面とかならまぁ使ってもいいかなーくらいの感じです。

まずはhtmlから。

<head>
  <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" />
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
  <script src="/main.js"></script>
</head>
  
<div id="datepicker"></div>

<form id="send_form" action="/create" method="post" onsubmit="sendForm();return false;">
  <input type="submit" value="送信">
</form>

jquery-ui.css, jquery.js, jquery-ui.jsを読み込んで、下に書いたmain.jsってのを読み込んでます。
で、カレンダーの表示部分は、

<input id="datepicker">

ってな感じで書くとフォーカスが当たった時にカレンダーが表示されるのが一般的な使い方ですが、

<div id="datepicker"></div>

ってな感じでdivを指定すると、ページが表示されたタイミングでカレンダーが出っ放しになります。

で、あとはmain.jsをゴリゴリっと書きます。

var current_year = null; // 表示されている年
var current_month = null; // 表示されている月
var selected_date = []; // 選択した年月日

$(function(){
    $('#datepicker').datepicker({
        dateFormat: 'yy-mm-dd',
        onSelect: function( select_date ){
            // selected_dateに入ってない場合は入れる。入ってる場合は削除。
            if ( selected_date[select_date] === undefined ) {
                selected_date[select_date] = 1;
            }
            else {
                delete selected_date[select_date];
            }

            setTimeout( function(){
                for ( i in selected_date) {
                    var data = i.split('-');
                    var year = data[0];
                    // 年が違う
                    if ( year != current_year ){ continue }
                    var month = data[1];
                    // 月が違う
                    if ( month != current_month ) { continue }
                    var day = data[2] * 1;

                    // 日を探して色をつける
                    $('.ui-datepicker-calendar a').each(function(){
                        var $this = $(this);
                        if ( $this.text() == day ) {
                            $this.parent('td').css('background-color','#F00');
                        }
                    });
                }
            }, 100);
        },
        onChangeMonthYear: function( year, month ) {
            current_year = year;
            current_month = month;

            setTimeout( function(){
                for ( i in selected_date ) {
                    var data = i.split('-');
                    var year = data[0];
                    if ( year != current_year ){ continue }
                    var month = data[1];
                    if ( month != current_month ) { continue }
                    var day = data[2] * 1;

                    $('.ui-datepicker-calendar a').each(function(){
                        var $this = $(this);
                        if ( $this.text() == day ) {
                            $this.parent('td').css('background-color','#F00');
                        }
                    });
                }
            }, 100);
        }
    });

    // current_year,current_monthを初期化
    var current = $.datepicker.formatDate('yy-mm-dd', $('#datepicker').datepicker('getDate') );
    if ( !current_year ) {
        var data = current.split('-');
        current_year = data[0];
        current_month = data[1] * 1;
    }
});

$.datepickerに用意されているEventですが、
onSelect: 日が選択されたら動くイベント
onChangeMonthYear: 月が変更されたら動くイベント
上のイベントが動いた時に、現在の年月で選択されている日に色を着け直す処理をただひたすらに回してるだけです。
全く持って効率がいいとは言えませんが・・。

これだけだと選択したデータをselected_dateに入れてるだけなんで、あとはAjaxで飛ばすなりformで送信するなり。
で、formで送信する為に下記のfunctionを追加してみた。
一番上に書いたhtmlのonsubmit="sendForm();"の中身ですね。

function sendForm(){
    // formにチェックされたcheckboxを追加していく(display:noneで)
    for ( i in selected_date ) {
        var input = '<input type="checkbox" name="date" value="' + i + '" checked="checked" style="display:none;">';
        $('#send_form').append( input );
    }

    // onsubmitを削除して、submit。
    $('#send_form').removeAttr('onsubmit').submit();
}

で、これをもうちょっとちゃんとやろうとするなら、そもそも複数の日が選択可能な別のライブラリを探すのが良いと思いますw
宗教上の理由等で、どうしてもjQueryUIでやらないと行けないならjQueryUIをオーバーライドして、day要素の出力時に、idを振るとかすれば、ループ回数が減ってもう少し効率が良くなるんじゃないかな・・。

 - jQuery