またどこかのCTOになった人のブログ

またどこかのCTOになった人が書いてます。最近はCakePHP3とConoHaのネタが多いです。

fullcalendar その1 〜とりあえずスケジュール表の外枠だけ作ってみた〜

転職してから4ヶ月が経過しました。
孤独なCTO活動もなかなか慣れてまいりました。
慣れただけであって、平気だというわけではないんですが。


さて。
今回はfullcalendarを使ってスケジュール表を作ってみました。
fullcalendarというものは、どこかの偉い人が作った高機能カレンダーJSライブラリです。

fullcalendar.io

スケジュール表ではないのですが、前職でfullcalendarを使って某機能を作成したことがありました。
が、その時は失敗しました。

datatablesもそうなのですが、JSライブラリなので何も考えないで使うと表示しようとしたデータを最初にまるっと読み込むのです。
なので、データ量が多いと当然動作が重くなったり画面が真っ白になったりします。というかしました。
何も考えないで作ってはいけないということを学んだのです(戒め)

やりたかったこと

・表示している月毎のデータだけを取得したい
・設定済みの予約をクリックしてモーダル表示で詳細を見たい
・設定済みの予約をカレンダー上でドラッグして日付変更したい
・カレンダーの日付をクリックして新規予定を設定したい

編集だとか削除だとか、そういうのはとりあえず置いておきます。

fullcalendarの準備

上にリンクを置いておきましたが、とりあえずfullcalendarをダウンロードして解凍して下さい。
解凍して出てきたディレクトリから、今回使用するのは以下のファイルです。

・JS本体として「fullcalendar.min.js」
・日本語対応として「ja.js」
・fullcalendarの見た目用に「fullcalendar.min.css

この辺を読み込んで下さい。
JQueryは3.1.1を使っています。
fullcalendar.min.jsはJQueryの後の方がいいんじゃないかなと思います、多分。

コントローラ側の記載

何も書きませんでした。

いわゆる管理画面的なものに今回のスケジュール表を載せましたので、CalendarsControllerみたいなものににindexアクションを作った程度です。
データ取得とかそういうのは全部Ajaxでやりました。
まぁAjax嫌いなんですけどね。

View側の記載

カレンダー表示はこんな感じで書きました。
例の如く、今回もBootstrapさんが大活躍です。

<div id="contents" class="container-fluid">
  <div class="row">
    <div class="col-xs-12">
      <div class="panel">
        <div class="panel-heading">
          スケジュール表
        </div>
        <div class="panel-body">
          <!-- メッセージ表示したい時はこの辺に -->
          <div class="row">
            <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"
              <div id="calendar"></div> <!-- ここがカレンダー表示部分 -->
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

パネルが好きなのです。
Bootstrap4はパネルなくなってるらしいですが、使ってるのはBootstrap3なのでいいです。
「パネルの中にカレンダーを表示」させるつもりで書いてます。

fullcalendarを着火

着火はJSで実行します。
カレンダーを表示するViewのどこかにJSを書けばOKです。

<script>
  $(document).ready(function() {
    $('#calendar').fullCalendar();
  });
</script>

これでカレンダーが表示されるんじゃないかなと思われます。

fullcalendarのプロパティ設定

上記のコードでカレンダーは表示されるのですが、色々と都合がよろしくないのでプロパティを追加することにします。
プロパティに関しては以下のページを参考にして下さい。

Documentation | FullCalendar

あまりに雑だし英語ばかりなので、サンプルとして今回自分が設定したプロパティを書いておきます。
参考にして下さい。

<script>
  $(document).ready(function() {
    $('#calendar').fullCalendar({
        header: {
          // fullcalendarのヘッダーに配置するボタン
          // 左側には「前月、翌月、今日」のボタン
          // 中央には表示している月
          // 右側には月表示、週表示、日表示、月予定
          left: 'prev,next today',
          center: 'title',
          right: 'month,agendaWeek,agendaDay,listMonth'
        },
        timeFormat: 'HH:mm', // 時間表示フォーマット
        timezone: 'Asia/Tokyo', // タイムゾーン設定
        eventLimit: true, // イベント増えた時にリンクボタン表示
        editable: true, // 編集可能設定
        slotEventOverlap: true, // イベントの見た目を重ねて表示
        selectable: true, // カレンダー空白部分のドラッグ可能
        selectHelper: true, // これをtrueにすると範囲設定できます
        selectMinDistance: 1 // 説明し難いので別途
    });
  });
</script>

「selectMinDistance」だけこちらで説明します。
fullcalendarさんはクリックイベントもドラッグイベントも取れるのですが、「selectMinDistanceに設定した間を超えたらドラッグイベントで扱うね」という設定らしいです。
これを設定しておかないと、クリックとドラッグでそれぞれ上手くイベントが取れなかったり意図しない動きになるので設定しておくといいです。
単位は何だったのか忘れてしまいました。秒じゃないとは思うのですが。
とりあえず「1」にしておけばいいと思います。適当ですいません。

fullcalendarのイベント設定

これは上に書いたプロパティ設定に続けて書くことにします

<script>
  $(document).ready(function() {
    $('#calendar').fullCalendar({
        header: {
          left: 'prev,next today',
          center: 'title',
          right: 'month,agendaWeek,agendaDay,listMonth'
        },
        timeFormat: 'HH:mm',
        timezone: 'Asia/Tokyo', 
        eventLimit: true, 
        editable: true, 
        slotEventOverlap: true, 
        selectable: true, 
        selectHelper: true, 
        selectMinDistance: 1, 
        events: function(start, end, timezone, callback) {
           // ページロード時に表示するカレンダーデータ取得イベント
        },
        eventClick: function(calEvent, jsEvent, view) {
           // カレンダーに設定したイベントクリック時のイベント
        },
        dayClick: function(date, jsEvent, view) {
           // カレンダー空白部分クリック時のイベント
        },
        select: function(start, end) {
           // カレンダー空白部分をドラッグして範囲指定した時のイベント
        },
        eventDrop: function(event, delta, revertFunc, jsEvent, ui, view) {
           // イベントをドラッグして別日に移動させた時のイベント
        }
    });
  });
</script>

パッと見がそれっぽくなってきました。
上に書いたコメント部分が重要なやつです。
あとはこの部分でAjax呼べばOKです。

何やら長くなってきてしまったので、一旦ここで切ってみます。
続きは次回の記事で書きます。