tosh diary

にっき

Pikaday.jsの土日と指定日(祝日etc)の色分け表示

カレンダーを実装する必要があって、Pikaday.jsを利用しました。

github.com

2ヶ月間表示など、色々と欲しい機能が付いていて助かったのですが

「土日祝を表示・選択させない」必要があり、少しソースを調整したのでメモ。

調整した内容

1) render functionに土日と祝日の判定を入れる

render: function(year, month, randId)
{
    var opts   = this._o,
        now    = new Date(),
        days   = getDaysInMonth(year, month),
        before = new Date(year, month, 1).getDay(),
        data   = [],
        row    = [],
        holidays = []; // 指定日(祝日)を設定
    holidays.push(new Date(2016,11,23), new Date(2016,11,29), new Date(2016,11,30));
    setToStartOfDay(now);
    if (opts.firstDay > 0) {
        before -= opts.firstDay;
        if (before < 0) {
            before += 7;
        }
    }
    var previousMonth = month === 0 ? 11 : month - 1,
        nextMonth = month === 11 ? 0 : month + 1,
        yearOfPreviousMonth = month === 0 ? year - 1 : year,
        yearOfNextMonth = month === 11 ? year + 1 : year,
        daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
    var cells = days + before,
        after = cells;
    while(after > 7) {
        after -= 7;
    }
    cells += 7 - after;
    for (var i = 0, r = 0; i < cells; i++)
    {
        var day = new Date(year, month, 1 + (i - before)),
                  isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
                  isToday = compareDates(day, now),
                  isEmpty = i < before || i >= (days + before),
                  dayNumber = 1 + (i - before),
                  monthNumber = month,
                  yearNumber = year,
                  isStartRange = opts.startRange && compareDates(opts.startRange, day),
                  isEndRange = opts.endRange && compareDates(opts.endRange, day),
                  isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
                  isDisabled = (opts.minDate && day < opts.minDate) ||
                               (opts.maxDate && day > opts.maxDate) ||
                               (opts.disableWeekends && isWeekend(day)) ||
                               (opts.disableDayFn && opts.disableDayFn(day)),
                  isHoliday = (day.getDay() === 0 || day.getDay() === 6);  // 土日を設定
        if(!isHoliday) {
            for(var j = 0; j < holidays.length; j++) {
                // 指定日を判定
                isHoliday = (holidays[j].getFullYear() === day.getFullYear() && holidays[j].getMonth() === day.getMonth() && holidays[j].getDate() === day.getDate());
                if(isHoliday) { break; }
            }
        }
        if (isEmpty) {
            if (i < before) {
                dayNumber = daysInPreviousMonth + dayNumber;
                monthNumber = previousMonth;
                yearNumber = yearOfPreviousMonth;
            } else {
                dayNumber = dayNumber - days;
                monthNumber = nextMonth;
                yearNumber = yearOfNextMonth;
            }
        }

        var dayConfig = {
            day: dayNumber,
            month: monthNumber,
            year: yearNumber,
            isSelected: isSelected,
            isToday: isToday,
            isDisabled: isDisabled,
            isEmpty: isEmpty,
            isStartRange: isStartRange,
            isEndRange: isEndRange,
            isInRange: isInRange,
            showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
            isHoliday: isHoliday  // プロパティを設定しておく
        };

2) pikaday.cssに追加する

.holiday {
    color: red;    
}

.is-disabled .pika-button.holiday,
.is-outside-current-month .pika-button.holiday {
    color: red;
}

// 選択させない
.is-holiday {
    pointer-events: none;
    cursor: default;
}

3) 308行目辺りでisHolidayを利用して、classを設定する

if (opts.isEndRange) {
    arr.push('is-endrange');
}
return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + ' ' + (opts.isHoliday ? 'is-holiday' : '') + '" aria-selected="' + ariaSelected + '">' +
         '<button class="pika-button pika-day ' + (opts.isHoliday ? 'holiday' : '') + '" type="button" ' +
            'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
                opts.day +
         '</button>' +
       '</td>';

こんな感じで出来る。

f:id:runble:20161208091237p:plain

正直、祝日はGoogleのCalendar APIとかである程度自動化したい。