Tech Sketch Bucket of Technical Chips by TIS Inc.

jQuery UI Datepicker-土・日・祝日・非営業日対応


jQueryjQuery UI は、とても便利です。各ブラウザのJavascript実装の差異を吸収してくれるだけでなく、ドラッグアンドドロップやタブビューなど様々なリッチなUIを利用することができます。あのIE6対応を考えなくても済むというだけでも、利用する価値があるというものです。
これらjQuery/jQuery UIは、コンシューマ向けのWebサイトのみならず、企業内の基幹業務用Webシステムであっても利用して当たり前、というほど普及していると言ってもよいでしょう。

ただし実際の業務システムで利用する際には、「ここをカスタマイズできれば!」という部分が出てくるものです。
jQuery/jQuery UIはオープンソースですから、ソースコードを直接修正してしまえば何でもカスタマイズできます。ただしそのような手段を取ると、今後リリースされるであろう新しいjQueryライブラリに更新するたびに、修正パッチを当て続けなければなりません。これでは運用が大変です。

実はjQuery UIには、個別のカスタマイズをしやすくするための拡張ポイントが準備されています。ライブラリ本体のソースコードにはなるべく手を付けず、できる限り拡張ポイントを利用するのがカスタマイズのコツです。

今回はjQuery UI Datepickerを拡張し、土・日・祝日・非営業日の背景色を変更し、選択不可にするという小ネタを紹介します。
datepicker.png


jQuery/jQuery UIのバージョン

本記事は、下記バージョンのjQuery/jQuery UIで検証しています。

javascriptのみで実現

まずはjavascriptのみで実現するバージョンです。javascript内に静的に休日情報が定義されておりajaxによる動的な情報取得が不必要です。以下のような場合におすすめです。

  1. 一度決めた祝日や非営業日は、基本的に変更されない
  2. 定期的にシステムメンテナンスをするタイミングが取れる
  3. 通信帯域が狭く、通信頻度はなるべく減らしたい

css

土・日・祝日・非営業日の背景色をCSSで定義します。

注意点:

  • .ui-state-defaultはjQuery UIが動的生成するclassです。将来のjQuery UIでは、違うクラス名になってしまう可能性があります。
    • ここはjQuery UIの内部構造に依存しています。イケテナイ・・・
  • .date-holidayXのXは、後述する「休日タイプ」に一致させます。この例では2種類ですが、もっと細分化することも可能です。

javascript

jQuery UI datepickerを拡張するjavascript本体です。
この例では、2011年と2012年の土・日・祝日・非営業日が定義されています。

実際の運用としては、このjsファイルを年に一回更新する形となります。
ブラウザや経路途中でのキャッシュに悪影響を受けないように、jsファイルのファイル名以降に「?更新日」をつけるようにし、ファイルを更新した際には更新日を変更するようにしましょう。

重要な拡張ポイントは、beforeShowDayイベントハンドラです。
このイベントハンドラは「カレンダーの各日が描画される直前」に呼び出され、戻り値として

 [その日は選択可能か?(true/false), その日に適用されるCSS, (必要であれば)popupするツールチップ]

という配列を返す必要があります。
このイベントハンドラ内部で、祝日・非営業日・土・日をチェックし、CSSを切り替え、日付選択を不可にしています。

html

上記のcssとjavascriptを利用するHTMLです。ひじょーにシンプルです。

cssとjavascriptの読み込み順序に注意してください。jQuery/jQuery UIのcss/jsのから読み込まれる必要があります。

祝日・非営業日情報をajaxで取得

上記の例では、祝日・非営業日情報はjavascript内部に静的に持っていました。この実装はサーバー・クライアント間の通信を必要としないため、通信負荷をかけないというメリットがありますが、「ユーザーやデータの状況に従って非営業日を動的に変更したい」というニーズに答えることは困難です。
そのため次は、休日情報をajaxで動的取得してみます。

サーバ側

サーバ側は何で作ってもかまいません。本記事では、

 http://server_url:3000/holidays/search.json に パラメータ year=2011&month=10 など

でPOSTリクエストした際に、holidaysの形式に従ったjsonが返ってくるようなサーバをrails3で作りました。

このサーバから取得されるjsonの例(見やすいように改行や空白を追加しています)

javascript

上記のjavascriptとやっている内容は同じですが、休日定義(holidays)をajaxで動的に追加していくようになっています。

重要な拡張ポイントは、beforeShowイベントハンドラとonChangeMonthYearイベントハンドラです。

beforeShowイベントハンドラは、カレンダーが描画される直前に呼び出されます。
引数のinputはdatepickerを対応付けたテキストフィールド、instはdatepickerそのものを指します。カレンダーが描画される際、テキストフィールドに既に値が入力されていればその月を、入力されていなければ当日の月が表示されます。その値を取得し、ajaxでその月の休日情報を取得しています。

onChangeMonthYearイベントハンドラは、描画されたカレンダーの月を変更したタイミングで呼び出されます。引数で描画する予定の年と月が与えられますので、ajaxで休日情報を取得しています。

cssとHTML

javascriptのみ版と同じ

さらなる拡張

上記のコードでひととおり動きますが、月を変更する毎にajaxでサーバアクセスを行うため、ちょっと非効率です。
サーバ側の休日テーブルの変更頻度にもよりますが、「onloadでその年の休日情報を非同期に取得する」、「月ごとではなく年ごとに休日情報を取得する or 前後数カ月分の休日情報を取得する」等、状況に応じてさらなるカスタマイズをしてください。

最後に

今回はここまでにします。
jQuery/jQuery UIをいじり倒して、幸せな開発を行ないましょう!