#213 Calendars (revised)
Learn how to add a calendar to your Rails app. Whether it be a date picker using jQuery UI or a full page calendar for browsing records, I will show you how to do it in this episode.
- Download:
- source codeProject Files in Zip (60.1 KB)
- mp4Full Size H.264 Video (23.4 MB)
- m4vSmaller H.264 Video (12.7 MB)
- webmFull Size VP8 Video (14.8 MB)
- ogvFull Size Theora Video (30.9 MB)
Resources
Date Picker
Gemfile
group :assets do # ... gem 'jquery-ui-rails' end
app/assets/javascripts/application.js
//= require jquery.ui.datepicker
app/assets/stylesheets/application.css
/* *= require jquery.ui.datepicker */
articles/_form.html.erb
<%= f.text_field :published_on %>
articles.js.coffee
jQuery -> $('#article_published_on').datepicker dateFormat: 'yy-mm-dd'
Calendar View
calendars_controller.rb
def index @articles = Article.all @articles_by_date = @articles.group_by(&:published_on) @date = params[:date] ? Date.parse(params[:date]) : Date.today end
index.html.erb
<div id="articles"> <h2 id="month"> <%= link_to "<", date: @date.prev_month %> <%= @date.strftime("%B %Y") %> <%= link_to ">", date: @date.next_month %> </h2> <%= calendar @date do |date| %> <%= date.day %> <% if @articles_by_date[date] %> <ul> <% @articles_by_date[date].each do |article| %> <li><%= link_to article.name, article %></li> <% end %> </ul> <% end %> <% end %> </div>
helpers/calendar_helper.rb
module CalendarHelper def calendar(date = Date.today, &block) Calendar.new(self, date, block).table end class Calendar < Struct.new(:view, :date, :callback) HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday] START_DAY = :sunday delegate :content_tag, to: :view def table content_tag :table, class: "calendar" do header + week_rows end end def header content_tag :tr do HEADER.map { |day| content_tag :th, day }.join.html_safe end end def week_rows weeks.map do |week| content_tag :tr do week.map { |day| day_cell(day) }.join.html_safe end end.join.html_safe end def day_cell(day) content_tag :td, view.capture(day, &callback), class: day_classes(day) end def day_classes(day) classes = [] classes << "today" if day == Date.today classes << "notmonth" if day.month != date.month classes.empty? ? nil : classes.join(" ") end def weeks first = date.beginning_of_month.beginning_of_week(START_DAY) last = date.end_of_month.end_of_week(START_DAY) (first..last).to_a.in_groups_of(7) end end end
app/assets/stylesheets/articles.css.scss
#articles .calendar { border-collapse: collapse; width: 100%; td, th { font-family: "Lucida Grande", arial, helvetica, sans-serif; font-size: 10px; padding: 6px; border: 1px solid #999; } th { background: #DDD; color: #666; text-align: center; width: 14.2857142857143%; } td { background: #FFF; color: #777; height: 80px; vertical-align: top; font-size: 16px; } .notmonth, .notmonth a { color: #CCC; } .today { background-color: #D7F2FF; } } #articles #month { margin: 0; padding-bottom: 10px; text-align: center; font-size: 22px; a { text-decoration: none; padding: 0 10px; color: #999; } } #articles ul { font-size: 11px; padding-left: 20px; }