読者です 読者をやめる 読者になる 読者になる

datepicker で祝日の背景色をつける。

先月、改正祝日法により、2016年より、8月11日を「山の日」祝日とすることが決まってから、
公開しているJava版の祝日計算の更新を行ったが、
jQuery UI datepicker もせめて祝日の日付の背景色だけでも休日の色として統一したくなった。

JavaとJavaScriptのソースだけを置いてある。→ http://sourceforge.jp/projects/jholiday/

これを使って以下のように表示する。
jQuery UI のサイトからダウンロードしたデモHTMLを何とかしたもの。。

f:id:posturan:20160313191240j:plain



複数月なら、、、

f:id:posturan:20160313191248j:plain



この表示の為に、補正する jQueryソースだけにしたかったのだが、元の CSS の構造上、
どうしたらいいか解らなくて、しかたなく jQuery-UI で配布された jquery.ui.datepicker.js を修正することになった。

jquery.ui.datepicker.js の変更箇所

カレンダーパネルを描画する _generateHTML メソッドの中、
  /* Generate the HTML for the current state of the date picker. */
のコメントがある
_generateHTML: function(inst) {
の中に、
 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
という1ヶ月分の tableタグで描画するループが存在する。
この for文の前に、
 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
という表示開始する日付を求める箇所が存在する。
これは描画する日付を表しておりこのDate型変数がforループで1日ずつ加算されて
td タグ、a タグで描画している。
この for ループの前に、作成したjholiday.js で定義した getDays メソッドで表示対象の月の
祝日、振替休日の日付(dayのみ)の配列を求めておく。→①
forループの中には描画の対象月の日付であるかどうかを求めている箇所がある。
  unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
    (minDate && printDate < minDate) || (maxDate && printDate > maxDate);

これはカレンダーとして描画した時の前後の月の日付が選択できないように描画する為で
unselectable という変数に設定している。
この unselectable を決定している実行の次に、で求めた配列の中に、printDate の日付が
存在するかを問い合わせる。
この問い合わせを行うのはカレンダーの対象でない前後の
月の日に対して、問い合わせを行わないために、unselectable == null を条件に
問い合わせをして、祝日、振替休日を判定する。
ここまでは、省略して書くと以下のようになる。
(コードが大きいので、変更箇所だけになってしまうが、、)

      printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
      // add holidayArray get
      var holidayArray = JHoliday.getDays(drawYear, drawMonth + 1);

      for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
         calender += "<tr>";
         tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
            this._get(inst, "calculateWeek")(printDate) + "</td>");
         for (dow = 0; dow < 7; dow++) { // create date picker days
            daySettings = (beforeShowDay ?
               beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
            otherMonth = (printDate.getMonth() !== drawMonth);
            unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
               (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
            // add holiday select
            var holiday = false;
            if (unselectable == null){
               var day = printDate.getDate();
               if ($.inArray(day, holidayArray) >= 0){
                  holiday = true;
               }
            }


日付の背景色は、a タグの属性で指定しているので、上で求めた箇所により
holiday = true の場合に、新規追加の css class名を追加する。
休日の時、ui-state-default は、残したいが残すとマウス hover の時に、デフォルトの
背景色に戻ってしまうので、しかたなく置き換える。

  (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +

という箇所があるので、
これを以下のように書き換える。

  (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='" +
  ((dow + firstDay + 6) % 7 === 6 || holiday ? "ui-datepicker-holiday" : "ui-state-default") +


ここで、追加した ui-datepicker-holiday に対して CSS で背景色を指定する。


jquery.ui.datepicker.js 読込の前に、祝日計算をする JavaScript
公開してる jholiday.js を指定する。

例)
<link rel="stylesheet" href="../../themes/base/jquery.ui.all.css">
<link rel="stylesheet" href="ui_datepicker_holiday.css">
<script src="../../jquery-1.10.2.js"></script>
<script src="../../ui/jquery.ui.core.js"></script>
<script src="../../ui/jquery.ui.widget.js"></script>
<script src="jholiday.js"></script>
<script src="../../ui/jquery.ui.datepicker.js"></script>
<link rel="stylesheet" href="../demos.css">