LoginSignup
22
27

More than 5 years have passed since last update.

Fullcalendarのかゆいところに手が届くオプションの設定方法

Last updated at Posted at 2015-03-01

概要

fullcalendarのオプションの動的、トリッキーな設定方法。
日本語の情報が無さすぎて書きたくなった。
$(document).readyなどは省略している

使用環境

Rails v4.1.0
fullcalendar v2.3.0
jquery-rails v3.1.2

今日の日付からカレンダーを表示する

calednar.js
firstDay:"today"

月曜日、日曜日などを0、1などの数字で設定すればその曜日から表示されるが
文字列の"today"を入れると常に"今日の日付"から表示される。あらビックリ
もちろんユーザーの設定などで動的に変更も可能。
その場合は事前に変数に入れてfirstDayに変数を設定すれば大丈夫。

ページ読み込み時に現在時刻を真ん中に表示する

scrollTimeで時間を"09:00"などで指定すればその時間をtopにして表示できるが
9時より前や夜の時間帯は予定を確認するのに毎回スクロールが必要。
この動作はストレスにしかならないので省く。

calednar.js
    var current_day = new Date();
    var current_hours = current_day.getHours() - 5;
    var current_minutes = current_day.getMinutes();
    var first_scroll_time = current_hours + ":" + current_minutes + ":00"
    var calendar =  $('#calendar').fullCalendar({
                        scrollTime: first_scroll_time
                    });

30分〜30分を1時間(または以降)単位でselectしたい

slotDuration: '00:30:00', //表示する時間軸の細かさ
snapDuration: '01:00:00', // 選択する時間間隔

通常予定は30分単位になってて、選択できるのは1時間がデフォルトがほとんど。
しかし上記の設定だと12:00〜13:00な選択できるが12:30:13:30などの中途半端な
時間帯が選択できない。
これってカレンダーとして致命傷。
こんなのオプションでなんとかなりそうに感じるが「ならない」
じゃあsnapDurationをslotと同じ30分にして「30分足したイベントをrenderする」
方法はどうか?
これは上手くいくが「selectHelper」とうまく噛み合わないので一瞬フリーズする。
他のselectConstraintなどオプションでも30分ずれるからダメ。
これはfullcalendar.jsの大元のファイルをいじるしかない。
確かこれはRailsでGemのfullcalendar−railsなどを使っている場合は不可なはず。
僕は最新のfullcalendar.jsのzipファイルをダウンロードしてvendor/assets以下に
置きました。
そのfullcalendar.jsのここの二カ所をいじるだけでOK!!!

fullcaelendar.js
//5860行目くらい?
computeRowCoords: function() {
        var originTop = this.el.offset().top;
        var items = [];
        var i;
        var item;
                  //ここ↓
        for (i = 0; i < 48; i++) {//デフォルトのslotDurationが30分なのでcolを48個に固定すれば常に30分単位で選択できるようにはなる。ここが1時間だと23個になって30分〜30分が選択できなくなる
            item = {
                top: originTop + this.computeTimeTop(this.computeSnapTime(i))//ここがsnapDurattionの時間を足して計算している部分。1時間だと一つのRowの幅が30分の倍になり結局30分〜30分が選べないので下記で修正する
            };
            if (i > 0) {
                items[i - 1].bottom = item.top;
            }
            items.push(item);
        }
        item.bottom = item.top + this.computeTimeTop(this.computeSnapTime(i));
        return items;
    },
fullcalendar.js
//5830行目くらい?
computeSnapTime: function(row) {
    return moment.duration(this.minTime + this.snapDuration * row);
    //ここで一つあたりの予定のtop,bottomの幅を作っているので全て30分単位に合わせる
    var select_harf_minutes = this.snapDuration / 1800000;
//slotが30分単位なのでミリ秒の1800000で割って30分単位に変換してる。15分単位なら900000で割ればOKかと。
        return moment.duration(this.minTime + this.snapDuration / select_harf_minutes * row);
    },

下のは編集はしないが動きを理解するのに役立った関数

fullcalendar.js
getCell: function(x, y) {
        var rowCoords = this.rowCoords;//全てのrowのtop値、bottom値を取得している
        var rowCnt = rowCoords.length;//rowの数を取得している。通常は30分選択で48個
        var colCoords = this.colCoords;
        var colCnt = colCoords.length;
        var hitRow = null;
        var hitCol = null;
        var i, coords;
        var cell;
        if (this.inBounds(x, y)) {
            //ここでy座標がtop,bottomの範囲内に収まっている要素をhitRowに代入している。上記二カ所を変更しないとrowCntが23個になってダメになり、coords.top,coords.bottomがそれぞれ30分単位の倍のピクセル数になりダメ
            for (i = 0; i < rowCnt; i++) {
                coords = rowCoords[i];
                if (y >= coords.top && y < coords.bottom) {
                    hitRow = i;
                    break;
                }
            }
            for (i = 0; i < colCnt; i++) {
                coords = colCoords[i];
                if (x >= coords.left && x < coords.right) {
                    hitCol = i;
                    break;
                }
            }
            if (hitRow !== null && hitCol !== null) {

                cell = this.grid.getCell(hitRow, hitCol); // expected to return a fresh object we can modify
                cell.grid = this.grid; // for CellDragListener's isCellsEqual. dragging between grids

                // make the coordinates available on the cell object
                $.extend(cell, rowCoords[hitRow], colCoords[hitCol]);

                return cell;
            }
        }

        return null;
    },

これでOK!ここを無理矢理30分に合わせているが取得したx,y軸に対するrowの幅を30分単位の幅に強制しただけなので他には影響しない。
ちゃんと12:30〜13:30でselectできて、なおかつ他のオプションがちゃんと動くことが
確認できました。

22
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
27