#概要
fullcalendarのオプションの動的、トリッキーな設定方法。
日本語の情報が無さすぎて書きたくなった。
$(document).readyなどは省略している
#使用環境
Rails v4.1.0
fullcalendar v2.3.0
jquery-rails v3.1.2
##今日の日付からカレンダーを表示する
firstDay:"today"
月曜日、日曜日などを0、1などの数字で設定すればその曜日から表示されるが
文字列の"today"を入れると常に"今日の日付"から表示される。あらビックリ
もちろんユーザーの設定などで動的に変更も可能。
その場合は事前に変数に入れてfirstDayに変数を設定すれば大丈夫。
##ページ読み込み時に現在時刻を真ん中に表示する
scrollTimeで時間を"09:00"などで指定すればその時間をtopにして表示できるが
9時より前や夜の時間帯は予定を確認するのに毎回スクロールが必要。
この動作はストレスにしかならないので省く。
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!!!
//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;
},
//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);
},
下のは編集はしないが動きを理解するのに役立った関数
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できて、なおかつ他のオプションがちゃんと動くことが
確認できました。