event-calendar 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +38 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +274 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/generators/event_calendar/USAGE +20 -0
- data/generators/event_calendar/event_calendar_generator.rb +50 -0
- data/generators/event_calendar/lib/insert_routes.rb +55 -0
- data/generators/event_calendar/templates/controller.rb.erb +12 -0
- data/generators/event_calendar/templates/helper.rb.erb +35 -0
- data/generators/event_calendar/templates/javascript.js +49 -0
- data/generators/event_calendar/templates/jq_javascript.js +35 -0
- data/generators/event_calendar/templates/migration.rb.erb +18 -0
- data/generators/event_calendar/templates/model.rb.erb +4 -0
- data/generators/event_calendar/templates/stylesheet.css +233 -0
- data/generators/event_calendar/templates/view.html.erb +6 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/lib/event_calendar.rb +189 -0
- data/lib/event_calendar/calendar_helper.rb +366 -0
- data/lib/event_calendar/railtie.rb +12 -0
- data/lib/generators/event_calendar/USAGE +20 -0
- data/lib/generators/event_calendar/event_calendar_generator.rb +92 -0
- data/lib/generators/event_calendar/templates/controller.rb.erb +12 -0
- data/lib/generators/event_calendar/templates/helper.rb.erb +35 -0
- data/lib/generators/event_calendar/templates/javascript.js +49 -0
- data/lib/generators/event_calendar/templates/jq_javascript.js +35 -0
- data/lib/generators/event_calendar/templates/migration.rb.erb +21 -0
- data/lib/generators/event_calendar/templates/model.rb.erb +3 -0
- data/lib/generators/event_calendar/templates/stylesheet.css +233 -0
- data/lib/generators/event_calendar/templates/view.html.erb +6 -0
- data/lib/tasks/event_calendar_tasks.rake +4 -0
- data/spec/event_calendar_spec.rb +78 -0
- data/spec/fixtures/models.rb +6 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +30 -0
- data/uninstall.rb +1 -0
- metadata +105 -0
data/init.rb
ADDED
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'event_calendar/railtie' if defined?(::Rails::Railtie)
|
2
|
+
module EventCalendar
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.send :extend, ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def has_event_calendar(options={})
|
11
|
+
cattr_accessor :start_at_field, :end_at_field
|
12
|
+
self.start_at_field = ( options[:start_at_field] ||= :start_at).to_s
|
13
|
+
self.end_at_field = ( options[:end_at_field] ||= :end_at ).to_s
|
14
|
+
alias_attribute :start_at, start_at_field unless start_at_field == 'start_at'
|
15
|
+
alias_attribute :end_at, end_at_field unless end_at_field == 'end_at'
|
16
|
+
before_save :adjust_all_day_dates
|
17
|
+
send :include, InstanceMethods
|
18
|
+
end
|
19
|
+
|
20
|
+
# For the given month, find the start and end dates
|
21
|
+
# Find all the events within this range, and create event strips for them
|
22
|
+
def event_strips_for_month(shown_date, first_day_of_week=0, find_options = {})
|
23
|
+
if first_day_of_week.is_a?(Hash)
|
24
|
+
find_options.merge!(first_day_of_week)
|
25
|
+
first_day_of_week = 0
|
26
|
+
end
|
27
|
+
strip_start, strip_end = get_start_and_end_dates(shown_date, first_day_of_week)
|
28
|
+
events = events_for_date_range(strip_start, strip_end, find_options)
|
29
|
+
event_strips = create_event_strips(strip_start, strip_end, events)
|
30
|
+
event_strips
|
31
|
+
end
|
32
|
+
|
33
|
+
# Expand start and end dates to show the previous month and next month's days,
|
34
|
+
# that overlap with the shown months display
|
35
|
+
def get_start_and_end_dates(shown_date, first_day_of_week=0)
|
36
|
+
# start with the first day of the given month
|
37
|
+
start_of_month = Date.civil(shown_date.year, shown_date.month, 1)
|
38
|
+
# the end of last month
|
39
|
+
strip_start = beginning_of_week(start_of_month, first_day_of_week)
|
40
|
+
# the beginning of next month, unless this month ended evenly on the last day of the week
|
41
|
+
if start_of_month.next_month == beginning_of_week(start_of_month.next_month, first_day_of_week)
|
42
|
+
# last day of the month is also the last day of the week
|
43
|
+
strip_end = start_of_month.next_month
|
44
|
+
else
|
45
|
+
# add the extra days from next month
|
46
|
+
strip_end = beginning_of_week(start_of_month.next_month + 7, first_day_of_week)
|
47
|
+
end
|
48
|
+
[strip_start, strip_end]
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get the events overlapping the given start and end dates
|
52
|
+
def events_for_date_range(start_d, end_d, find_options = {})
|
53
|
+
self.scoped(find_options).find(
|
54
|
+
:all,
|
55
|
+
:conditions => [ "(? <= #{self.end_at_field}) AND (#{self.start_at_field}< ?)", start_d.to_time.utc, end_d.to_time.utc ],
|
56
|
+
:order => "#{self.start_at_field} ASC"
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create the various strips that show evetns
|
61
|
+
def create_event_strips(strip_start, strip_end, events)
|
62
|
+
# create an inital event strip, with a nil entry for every day of the displayed days
|
63
|
+
event_strips = [[nil] * (strip_end - strip_start + 1)]
|
64
|
+
|
65
|
+
events.each do |event|
|
66
|
+
cur_date = event.start_at.to_date
|
67
|
+
end_date = event.end_at.to_date
|
68
|
+
cur_date, end_date = event.clip_range(strip_start, strip_end)
|
69
|
+
start_range = (cur_date - strip_start).to_i
|
70
|
+
end_range = (end_date - strip_start).to_i
|
71
|
+
|
72
|
+
# make sure the event is within our viewing range
|
73
|
+
if (start_range <= end_range) and (end_range >= 0)
|
74
|
+
range = start_range..end_range
|
75
|
+
|
76
|
+
open_strip = space_in_current_strips?(event_strips, range)
|
77
|
+
|
78
|
+
if open_strip.nil?
|
79
|
+
# no strips open, make a new one
|
80
|
+
new_strip = [nil] * (strip_end - strip_start + 1)
|
81
|
+
range.each {|r| new_strip[r] = event}
|
82
|
+
event_strips << new_strip
|
83
|
+
else
|
84
|
+
# found an open strip, add this event to it
|
85
|
+
range.each {|r| open_strip[r] = event}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
event_strips
|
90
|
+
end
|
91
|
+
|
92
|
+
def space_in_current_strips?(event_strips, range)
|
93
|
+
open_strip = nil
|
94
|
+
for strip in event_strips
|
95
|
+
strip_is_open = true
|
96
|
+
range.each do |r|
|
97
|
+
# overlapping events on this strip
|
98
|
+
if !strip[r].nil?
|
99
|
+
strip_is_open = false
|
100
|
+
break
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if strip_is_open
|
105
|
+
open_strip = strip
|
106
|
+
break
|
107
|
+
end
|
108
|
+
end
|
109
|
+
open_strip
|
110
|
+
end
|
111
|
+
|
112
|
+
def days_between(first, second)
|
113
|
+
if first > second
|
114
|
+
second + (7 - first)
|
115
|
+
else
|
116
|
+
second - first
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def beginning_of_week(date, start = 0)
|
121
|
+
days_to_beg = days_between(start, date.wday)
|
122
|
+
date - days_to_beg
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
# Instance Methods
|
128
|
+
# Override in your model as needed
|
129
|
+
module InstanceMethods
|
130
|
+
def year
|
131
|
+
date.year
|
132
|
+
end
|
133
|
+
|
134
|
+
def month
|
135
|
+
date.month
|
136
|
+
end
|
137
|
+
|
138
|
+
def day
|
139
|
+
date.day
|
140
|
+
end
|
141
|
+
|
142
|
+
def all_day
|
143
|
+
self[:all_day]
|
144
|
+
end
|
145
|
+
|
146
|
+
def color
|
147
|
+
self[:color] || '#9aa4ad'
|
148
|
+
end
|
149
|
+
|
150
|
+
def days
|
151
|
+
end_at.to_date - start_at.to_date
|
152
|
+
end
|
153
|
+
|
154
|
+
# start_d - start of the month, or start of the week
|
155
|
+
# end_d - end of the month, or end of the week
|
156
|
+
def clip_range(start_d, end_d)
|
157
|
+
# make sure we are comparing date objects to date objects,
|
158
|
+
# otherwise timezones can cause problems
|
159
|
+
start_at_d = start_at.to_date
|
160
|
+
end_at_d = end_at.to_date
|
161
|
+
# Clip start date, make sure it also ends on or after the start range
|
162
|
+
if (start_at_d < start_d and end_at_d >= start_d)
|
163
|
+
clipped_start = start_d
|
164
|
+
else
|
165
|
+
clipped_start = start_at_d
|
166
|
+
end
|
167
|
+
|
168
|
+
# Clip end date
|
169
|
+
if (end_at_d > end_d)
|
170
|
+
clipped_end = end_d
|
171
|
+
else
|
172
|
+
clipped_end = end_at_d
|
173
|
+
end
|
174
|
+
[clipped_start, clipped_end]
|
175
|
+
end
|
176
|
+
|
177
|
+
def adjust_all_day_dates
|
178
|
+
if self[:all_day]
|
179
|
+
self[:start_at] = self[:start_at].beginning_of_day
|
180
|
+
if self[:end_at]
|
181
|
+
self[:end_at] = self[:end_at].beginning_of_day + 1.day - 1.second
|
182
|
+
else
|
183
|
+
self[:end_at] = self[:start_at].beginning_of_day + 1.day - 1.second
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,366 @@
|
|
1
|
+
module EventCalendar
|
2
|
+
module CalendarHelper
|
3
|
+
|
4
|
+
# Returns an HTML calendar which can show multiple, overlapping events across calendar days and rows.
|
5
|
+
# Customize using CSS, the below options, and by passing in a code block.
|
6
|
+
#
|
7
|
+
# The following are optional, available for customizing the default behaviour:
|
8
|
+
# :month => Time.now.month # The month to show the calendar for. Defaults to current month.
|
9
|
+
# :year => Time.now.year # The year to show the calendar for. Defaults to current year.
|
10
|
+
# :dates => (start_date .. end_date) # Show specific range of days. Defaults to :year, :month.
|
11
|
+
# :abbrev => true # Abbreviate day names. Reads from the abbr_day_names key in the localization file.
|
12
|
+
# :first_day_of_week => 0 # Renders calendar starting on Sunday. Use 1 for Monday, and so on.
|
13
|
+
# :show_today => true # Highlights today on the calendar using CSS class.
|
14
|
+
# :month_name_text => nil # Displayed center in header row.
|
15
|
+
# Defaults to current month name from Date::MONTHNAMES hash.
|
16
|
+
# :previous_month_text => nil # Displayed left of the month name if set
|
17
|
+
# :next_month_text => nil # Displayed right of the month name if set
|
18
|
+
# :event_strips => [] # An array of arrays, encapsulating the event rows on the calendar
|
19
|
+
#
|
20
|
+
# :width => nil # Width of the calendar, if none is set then it will stretch the container's width
|
21
|
+
# :height => 500 # Approx minimum total height of the calendar (excluding the header).
|
22
|
+
# Height could get added if a day has too many event's to fit.
|
23
|
+
# :day_names_height => 18 # Height of the day names table (included in the above 'height' option)
|
24
|
+
# :day_nums_height => 18 # Height of the day numbers tables (included in the 'height' option)
|
25
|
+
# :event_height => 18 # Height of an individual event row
|
26
|
+
# :event_margin => 1 # Spacing of the event rows
|
27
|
+
# :event_padding_top => 1 # Padding on the top of the event rows (increase to move text down)
|
28
|
+
#
|
29
|
+
# :use_all_day => false # If set to true, will check for an 'all_day' boolean field when displaying an event.
|
30
|
+
# If it is an all day event, or the event is multiple days, then it will display as usual.
|
31
|
+
# Otherwise it will display without a background color bar.
|
32
|
+
# :use_javascript => true # Outputs HTML with inline javascript so events spanning multiple days will be highlighted.
|
33
|
+
# If this option is false, cleaner HTML will be output, but events spanning multiple days will
|
34
|
+
# not be highlighted correctly on hover, so it is only really useful if you know your calendar
|
35
|
+
# will only have single-day events. Defaults to true.
|
36
|
+
# :link_to_day_action => false # If controller action is passed,
|
37
|
+
# the day number will be a link. Override the day_link method for greater customization.
|
38
|
+
#
|
39
|
+
# For more customization, you can pass a code block to this method
|
40
|
+
# The varibles you have to work with in this block are passed in an agruments hash:
|
41
|
+
# :event => The event to be displayed.
|
42
|
+
# :day => The day the event is displayed on. Usually the first day of the event, or the first day of the week,
|
43
|
+
# if the event spans a calendar row.
|
44
|
+
# :options => All the calendar options in use. (User defined and defaults merged.)
|
45
|
+
#
|
46
|
+
# For example usage, see README.
|
47
|
+
#
|
48
|
+
def calendar(options = {}, &block)
|
49
|
+
block ||= Proc.new {|d| nil}
|
50
|
+
|
51
|
+
defaults = {
|
52
|
+
:year => (Time.zone || Time).now.year,
|
53
|
+
:month => (Time.zone || Time).now.month,
|
54
|
+
:abbrev => true,
|
55
|
+
:first_day_of_week => 0,
|
56
|
+
:show_today => true,
|
57
|
+
:month_name_text => (Time.zone || Time).now.strftime("%B %Y"),
|
58
|
+
:previous_month_text => nil,
|
59
|
+
:next_month_text => nil,
|
60
|
+
:event_strips => [],
|
61
|
+
|
62
|
+
# it would be nice to have these in the CSS file
|
63
|
+
# but they are needed to perform height calculations
|
64
|
+
:width => nil,
|
65
|
+
:height => 500,
|
66
|
+
:day_names_height => 18,
|
67
|
+
:day_nums_height => 18,
|
68
|
+
:event_height => 18,
|
69
|
+
:event_margin => 1,
|
70
|
+
:event_padding_top => 2,
|
71
|
+
|
72
|
+
:use_all_day => false,
|
73
|
+
:use_javascript => true,
|
74
|
+
:link_to_day_action => false
|
75
|
+
}
|
76
|
+
options = defaults.merge options
|
77
|
+
|
78
|
+
# default month name for the given number
|
79
|
+
options[:month_name_text] ||= I18n.translate(:'date.month_names')[options[:month]]
|
80
|
+
|
81
|
+
# make the height calculations
|
82
|
+
# tricky since multiple events in a day could force an increase in the set height
|
83
|
+
height = options[:day_names_height]
|
84
|
+
row_heights = cal_row_heights(options)
|
85
|
+
row_heights.each do |row_height|
|
86
|
+
height += row_height
|
87
|
+
end
|
88
|
+
|
89
|
+
# the first and last days of this calendar month
|
90
|
+
if options[:dates].is_a?(Range)
|
91
|
+
first = options[:dates].begin
|
92
|
+
last = options[:dates].end
|
93
|
+
else
|
94
|
+
first = Date.civil(options[:year], options[:month], 1)
|
95
|
+
last = Date.civil(options[:year], options[:month], -1)
|
96
|
+
end
|
97
|
+
|
98
|
+
# create the day names array [Sunday, Monday, etc...]
|
99
|
+
day_names = []
|
100
|
+
if options[:abbrev]
|
101
|
+
day_names.concat(I18n.translate(:'date.abbr_day_names'))
|
102
|
+
else
|
103
|
+
day_names.concat(I18n.translate(:'date.day_names'))
|
104
|
+
end
|
105
|
+
options[:first_day_of_week].times do
|
106
|
+
day_names.push(day_names.shift)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Build the HTML string
|
110
|
+
cal = ""
|
111
|
+
|
112
|
+
# outer calendar container
|
113
|
+
cal << %(<div class="ec-calendar")
|
114
|
+
cal << %(style="width: #{options[:width]}px;") if options[:width]
|
115
|
+
cal << %(>)
|
116
|
+
|
117
|
+
# table header, including the monthname and links to prev & next month
|
118
|
+
cal << %(<table class="ec-calendar-header" cellpadding="0" cellspacing="0">)
|
119
|
+
cal << %(<thead><tr>)
|
120
|
+
if options[:previous_month_text] or options[:next_month_text]
|
121
|
+
cal << %(<th colspan="2" class="ec-month-nav ec-previous-month">#{options[:previous_month_text]}</th>)
|
122
|
+
colspan = 3
|
123
|
+
else
|
124
|
+
colspan = 7
|
125
|
+
end
|
126
|
+
cal << %(<th colspan="#{colspan}" class="ec-month-name">#{options[:month_name_text]}</th>)
|
127
|
+
if options[:next_month_text]
|
128
|
+
cal << %(<th colspan="2" class="ec-month-nav ec-next-month">#{options[:next_month_text]}</th>)
|
129
|
+
end
|
130
|
+
cal << %(</tr></thead></table>)
|
131
|
+
|
132
|
+
# body container (holds day names and the calendar rows)
|
133
|
+
cal << %(<div class="ec-body" style="height: #{height}px;">)
|
134
|
+
|
135
|
+
# day names
|
136
|
+
cal << %(<table class="ec-day-names" style="height: #{options[:day_names_height]}px;" cellpadding="0" cellspacing="0">)
|
137
|
+
cal << %(<tbody><tr>)
|
138
|
+
day_names.each do |day_name|
|
139
|
+
cal << %(<th class="ec-day-name" title="#{day_name}">#{day_name}</th>)
|
140
|
+
end
|
141
|
+
cal << %(</tr></tbody></table>)
|
142
|
+
|
143
|
+
# container for all the calendar rows
|
144
|
+
cal << %(<div class="ec-rows" style="top: #{options[:day_names_height]}px; )
|
145
|
+
cal << %(height: #{height - options[:day_names_height]}px;">)
|
146
|
+
|
147
|
+
# initialize loop variables
|
148
|
+
first_day_of_week = beginning_of_week(first, options[:first_day_of_week])
|
149
|
+
last_day_of_week = end_of_week(first, options[:first_day_of_week])
|
150
|
+
last_day_of_cal = end_of_week(last, options[:first_day_of_week])
|
151
|
+
row_num = 0
|
152
|
+
top = 0
|
153
|
+
|
154
|
+
# go through a week at a time, until we reach the end of the month
|
155
|
+
while(last_day_of_week <= last_day_of_cal)
|
156
|
+
cal << %(<div class="ec-row" style="top: #{top}px; height: #{row_heights[row_num]}px;">)
|
157
|
+
top += row_heights[row_num]
|
158
|
+
|
159
|
+
# this weeks background table
|
160
|
+
cal << %(<table class="ec-row-bg" cellpadding="0" cellspacing="0">)
|
161
|
+
cal << %(<tbody><tr>)
|
162
|
+
first_day_of_week.upto(first_day_of_week+6) do |day|
|
163
|
+
today_class = (day == Date.today) ? "ec-today-bg" : ""
|
164
|
+
cal << %(<td class="ec-day-bg #{today_class}"> </td>)
|
165
|
+
end
|
166
|
+
cal << %(</tr></tbody></table>)
|
167
|
+
|
168
|
+
# calendar row
|
169
|
+
cal << %(<table class="ec-row-table" cellpadding="0" cellspacing="0">)
|
170
|
+
cal << %(<tbody>)
|
171
|
+
|
172
|
+
# day numbers row
|
173
|
+
cal << %(<tr>)
|
174
|
+
first_day_of_week.upto(last_day_of_week) do |day|
|
175
|
+
cal << %(<td class="ec-day-header )
|
176
|
+
cal << %(ec-today-header ) if options[:show_today] and (day == Date.today)
|
177
|
+
cal << %(ec-other-month-header ) if (day < first) || (day > last)
|
178
|
+
cal << %(ec-weekend-day-header) if weekend?(day)
|
179
|
+
cal << %(" style="height: #{options[:day_nums_height]}px;">)
|
180
|
+
if options[:link_to_day_action]
|
181
|
+
cal << day_link(day.day, day, options[:link_to_day_action])
|
182
|
+
else
|
183
|
+
cal << %(#{day.day})
|
184
|
+
end
|
185
|
+
cal << %(</td>)
|
186
|
+
end
|
187
|
+
cal << %(</tr>)
|
188
|
+
|
189
|
+
# event rows for this day
|
190
|
+
# for each event strip, create a new table row
|
191
|
+
options[:event_strips].each do |strip|
|
192
|
+
cal << %(<tr>)
|
193
|
+
# go through through the strip, for the entries that correspond to the days of this week
|
194
|
+
strip[row_num*7, 7].each_with_index do |event, index|
|
195
|
+
day = first_day_of_week + index
|
196
|
+
|
197
|
+
if event
|
198
|
+
# get the dates of this event that fit into this week
|
199
|
+
dates = event.clip_range(first_day_of_week, last_day_of_week)
|
200
|
+
# if the event (after it has been clipped) starts on this date,
|
201
|
+
# then create a new cell that spans the number of days
|
202
|
+
if dates[0] == day.to_date
|
203
|
+
# check if we should display the bg color or not
|
204
|
+
no_bg = no_event_bg?(event, options)
|
205
|
+
|
206
|
+
cal << %(<td class="ec-event-cell" colspan="#{(dates[1]-dates[0]).to_i + 1}" )
|
207
|
+
cal << %(style="padding-top: #{options[:event_margin]}px;">)
|
208
|
+
cal << %(<div class="ec-event ec-event-#{event.id} )
|
209
|
+
if no_bg
|
210
|
+
cal << %(ec-event-no-bg" )
|
211
|
+
cal << %(style="color: #{event.color}; )
|
212
|
+
else
|
213
|
+
cal << %(ec-event-bg" )
|
214
|
+
cal << %(style="background-color: #{event.color}; )
|
215
|
+
end
|
216
|
+
cal << %(padding-top: #{options[:event_padding_top]}px; )
|
217
|
+
cal << %(height: #{options[:event_height] - options[:event_padding_top]}px;" )
|
218
|
+
if options[:use_javascript]
|
219
|
+
# custom attributes needed for javascript event highlighting
|
220
|
+
cal << %(data-event-id="#{event.id}" data-color="#{event.color}" )
|
221
|
+
end
|
222
|
+
cal << %(>)
|
223
|
+
|
224
|
+
# add a left arrow if event is clipped at the beginning
|
225
|
+
if event.start_at.to_date < dates[0]
|
226
|
+
cal << %(<div class="ec-left-arrow"></div>)
|
227
|
+
end
|
228
|
+
# add a right arrow if event is clipped at the end
|
229
|
+
if event.end_at.to_date > dates[1]
|
230
|
+
cal << %(<div class="ec-right-arrow"></div>)
|
231
|
+
end
|
232
|
+
|
233
|
+
if no_bg
|
234
|
+
cal << %(<div class="ec-bullet" style="background-color: #{event.color};"></div>)
|
235
|
+
# make sure anchor text is the event color
|
236
|
+
# here b/c CSS 'inherit' color doesn't work in all browsers
|
237
|
+
cal << %(<style type="text/css">.ec-event-#{event.id} a { color: #{event.color}; }</style>)
|
238
|
+
end
|
239
|
+
|
240
|
+
if block_given?
|
241
|
+
# add the additional html that was passed as a block to this helper
|
242
|
+
cal << block.call({:event => event, :day => day.to_date, :options => options})
|
243
|
+
else
|
244
|
+
# default content in case nothing is passed in
|
245
|
+
cal << %(<a href="/events/#{event.id}" title="#{h(event.name)}">#{h(event.name)}</a>)
|
246
|
+
end
|
247
|
+
|
248
|
+
cal << %(</div></td>)
|
249
|
+
end
|
250
|
+
|
251
|
+
else
|
252
|
+
# there wasn't an event, so create an empty cell and container
|
253
|
+
cal << %(<td class="ec-event-cell ec-no-event-cell" )
|
254
|
+
cal << %(style="padding-top: #{options[:event_margin]}px;">)
|
255
|
+
cal << %(<div class="ec-event" )
|
256
|
+
cal << %(style="padding-top: #{options[:event_padding_top]}px; )
|
257
|
+
cal << %(height: #{options[:event_height] - options[:event_padding_top]}px;" )
|
258
|
+
cal << %(>)
|
259
|
+
cal << %( </div></td>)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
cal << %(</tr>)
|
263
|
+
end
|
264
|
+
|
265
|
+
cal << %(</tbody></table>)
|
266
|
+
cal << %(</div>)
|
267
|
+
|
268
|
+
# increment the calendar row we are on, and the week
|
269
|
+
row_num += 1
|
270
|
+
first_day_of_week += 7
|
271
|
+
last_day_of_week += 7
|
272
|
+
end
|
273
|
+
|
274
|
+
cal << %(</div>)
|
275
|
+
cal << %(</div>)
|
276
|
+
cal << %(</div>)
|
277
|
+
end
|
278
|
+
|
279
|
+
# override this in your own helper for greater control
|
280
|
+
def day_link(text, date, day_action)
|
281
|
+
link_to(text, params.merge(:action => day_action, :year => date.year, :month => date.month, :day => date.day), :class => 'ec-day-link')
|
282
|
+
end
|
283
|
+
|
284
|
+
# check if we should display without a background color
|
285
|
+
def no_event_bg?(event, options)
|
286
|
+
options[:use_all_day] && !event.all_day && event.days == 0
|
287
|
+
end
|
288
|
+
|
289
|
+
# default html for displaying an event's time
|
290
|
+
# to customize: override, or do something similar, in your helper
|
291
|
+
def display_event_time(event, day)
|
292
|
+
time = event.start_at
|
293
|
+
if !event.all_day and time.to_date == day
|
294
|
+
# try to make it display as short as possible
|
295
|
+
fmt = (time.min == 0) ? "%l" : "%l:%M"
|
296
|
+
t = time.strftime(fmt)
|
297
|
+
am_pm = time.strftime("%p") == "PM" ? "p" : ""
|
298
|
+
t += am_pm
|
299
|
+
%(<span class="ec-event-time">#{t}</span>)
|
300
|
+
else
|
301
|
+
""
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
private
|
306
|
+
|
307
|
+
# calculate the height of each row
|
308
|
+
# by default, it will be the height option minus the day names height,
|
309
|
+
# divided by the total number of calendar rows
|
310
|
+
# this gets tricky, however, if there are too many event rows to fit into the row's height
|
311
|
+
# then we need to add additional height
|
312
|
+
def cal_row_heights(options)
|
313
|
+
# number of rows is the number of days in the event strips divided by 7
|
314
|
+
num_cal_rows = options[:event_strips].first.size / 7
|
315
|
+
# the row will be at least this big
|
316
|
+
min_height = (options[:height] - options[:day_names_height]) / num_cal_rows
|
317
|
+
row_heights = []
|
318
|
+
num_event_rows = 0
|
319
|
+
# for every day in the event strip...
|
320
|
+
1.upto(options[:event_strips].first.size+1) do |index|
|
321
|
+
num_events = 0
|
322
|
+
# get the largest event strip that has an event on this day
|
323
|
+
options[:event_strips].each_with_index do |strip, strip_num|
|
324
|
+
num_events = strip_num + 1 unless strip[index-1].blank?
|
325
|
+
end
|
326
|
+
# get the most event rows for this week
|
327
|
+
num_event_rows = [num_event_rows, num_events].max
|
328
|
+
# if we reached the end of the week, calculate this row's height
|
329
|
+
if index % 7 == 0
|
330
|
+
total_event_height = options[:event_height] + options[:event_margin]
|
331
|
+
calc_row_height = (num_event_rows * total_event_height) + options[:day_nums_height] + options[:event_margin]
|
332
|
+
row_height = [min_height, calc_row_height].max
|
333
|
+
row_heights << row_height
|
334
|
+
num_event_rows = 0
|
335
|
+
end
|
336
|
+
end
|
337
|
+
row_heights
|
338
|
+
end
|
339
|
+
|
340
|
+
#
|
341
|
+
# helper methods for working with a calendar week
|
342
|
+
#
|
343
|
+
|
344
|
+
def days_between(first, second)
|
345
|
+
if first > second
|
346
|
+
second + (7 - first)
|
347
|
+
else
|
348
|
+
second - first
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def beginning_of_week(date, start = 0)
|
353
|
+
days_to_beg = days_between(start, date.wday)
|
354
|
+
date - days_to_beg
|
355
|
+
end
|
356
|
+
|
357
|
+
def end_of_week(date, start = 0)
|
358
|
+
beg = beginning_of_week(date, start)
|
359
|
+
beg + 6
|
360
|
+
end
|
361
|
+
|
362
|
+
def weekend?(date)
|
363
|
+
[0, 6].include?(date.wday)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|