6
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jsとかややこしいの使わずRailsでカスタム自由度の高いカレンダー実装

Last updated at Posted at 2016-09-29

カレンダー実装をするために色々探してたんですが、jqueryプラグインとかgem使ったらいじりにくいし、これってのがなく、しょうがなく色々参考にしながら1から作りました。

誰かのお役に立てば幸いです。

見た目はこんな感じです。

さっそくコード

先ずはカレンダーの箱

ちょっと一工夫いるのは条件によって

を出したり消したりしてるとこですね。
そこだけです。
基本的に見れば分かるコードだと思うので解説は割愛します。
ちなみに

を参考にしてます。

html.erb


<div class="event-calendar">
    <table>
        <caption>2016年9月</caption>
        <tbody>
            <tr>
                <th>日</th>
                <th>月</th>
                <th>火</th>
                <th>水</th>
                <th>木</th>
                <th>金</th>
                <th>土</th>
            </tr>
            <% @calendar_days.each_with_index do |day, i| %>
                <% if i == 0 || i % 7 == 0 %>
                    <tr>
                <% end %>
                <td>
                    <p>
                        <%= day %>
                    </p>
                    <div>
                        <!-- ここにカレンダー1日単位で情報埋める -->
                    </div>
                </td>
                <% if i !=  0 && (i + 1) % 7 == 0 %>
                    </tr>
                <% end %>
            <% end %>
        </tbody>
    </table>
</div>

で、次に@calendar_daysに突っ込む値です

ちょっとめんどくさいアルゴリズム

けっこう苦肉りながら書いたので、もっといい方法あるだろって感じですが一旦こんな感じです。

全体としては、月の最初の日より前の部分と、月の最後の日より後の、よくカレンダーでグレーになってる過不足部分(なんて呼ぶんでしょうあれ)を、integerのarrayにして、最終的に当月の1~30日の配列と足してます。


    def get_calendar_dates(date)
      get_pre_shortage_days(date) + (1..date.end_of_month.day).to_a + get_post_shortage_days(date)
    end

    # その月の、"29 30" 1 のようなカレンダー不足分
    def get_pre_shortage_days(date)
      beginning_day = date.beginning_of_month
       return 0 if beginning_day.wday == 0
       pre_shortage_day = beginning_day - beginning_day.wday.days
       return (pre_shortage_day.day..pre_shortage_day.end_of_month.day).to_a
    end

    def get_post_shortage_days(date)
      end_day = date.end_of_month
      return 0 if end_day.wday == 6
      post_shortage_day = end_day + -(end_day.wday - 6).days
      return (1..post_shortage_day.day).to_a
    end
  end

部分的な解説

配列の足し算、便利です。

[1, 2, 3] + [4, 5, 6]
=> [1, 2, 3, 4, 5, 6]

肝になったのは以下の処理です。
これで日曜日〜土曜日までが0~6でとれるので、それで日を前後させてます。

Date.today.wday

ちなみに前後させるのに使ってる処理ですが、以下のように日付って足し引きできて便利です。

Date.today + 6.days

あとはrange型をarray型に変えるのも重宝しました。最初からarrayでもっと簡単にできそうな気配しかないですが。


(1..2).to_a
=> [1, 2]

scssについて

あるサイトを参考にして以下のようなscssを書きました。


div.event-calendar {
  float: left;

  table {
    width: 325px;
    margin-right: 5px;

    caption {
      font-size: 14px;
      color: #479384;
      border: 1px solid #b9b9b9;
      border-bottom: none;
      padding: 14px 0 12px;
      text-align: center;
    }

    tbody {
      display: table-row-group;
      vertical-align: middle;
      border-color: inherit;

      tr {
        display: table-row-group;
        vertical-align: inherit;
        border-color: inherit;

        th {
          width: 325px;
          text-align: center;
          vertical-align: top;
          color: #479384;
          background-color: #ecf7f5;
          border: 1px solid #b9b9b9;
          padding: 6px;
        }

        td {
          text-align: center;
          border: 1px solid #b9b9b9;
          font-size: 11px;
          width: 14%;
          height: 60px;

          i {
            font-size: 20px;
          }
        }
      }
    }
  }
}

稚拙な説明が極まってますが、誰かのお役に立てれば幸いです。

6
12
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
6
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?