simple_calendar 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae8f18ccce8e55fd2c7caefb28f9260befdb50c8
4
- data.tar.gz: ed5657eb62db1fee6021f516f935eed13c55335c
3
+ metadata.gz: 4ac05b82caf3c5475d9890349e7fe90fb9c536d1
4
+ data.tar.gz: df0ee7c7ba1fc634b41aa703dde69b89ec1040a5
5
5
  SHA512:
6
- metadata.gz: 687581a924042ef175fede1beb7fbf550dbbf5e8a936b7365d6b9c362d9484216c092bcc80abfcf3a116dff5184758393db77514c2023285662b86417e73170c
7
- data.tar.gz: 2d70ac7b3b28297e0e6cdbf457078240dbadcff2ed0635d1f4fccae5e45acc722ebc5814367137ca9001908bbc51872987fb03c0540ffe2b00ad3ba6da5c25a8
6
+ metadata.gz: af7ea6649813615d366c6915e883ee128a125526308e8caeb960da9552046d70407fe5c6dc87cf9f29effec7710064d181a2fb25f8e3f65782392ef2a1e7388c
7
+ data.tar.gz: ae67ff184ff36292f9c6ab38a55159c0d390a439436d49b33f577aaa5e3ed4268e17e8075038c116dbd6e8ae206f8f13e9d1d8c2945d1c80dccc4784fa716063
data/README.md CHANGED
@@ -17,12 +17,12 @@ Installation
17
17
 
18
18
  Just add this into your Gemfile followed by a bundle install:
19
19
 
20
- gem "simple_calendar", "~> 1.0.0"
20
+ gem "simple_calendar", "~> 1.1.0"
21
21
 
22
22
  Usage
23
23
  -----
24
24
 
25
- Generating calendars is extremely simple with simple_calendar in version 1.0.
25
+ Generating calendars is extremely simple with simple_calendar in version 1.1.
26
26
 
27
27
  The first parameter is a symbol that looks up the current date in
28
28
  `params`. If no date is found, it will use the current date.
@@ -33,22 +33,20 @@ In these examples, we're using `:start_date` which is the default.
33
33
 
34
34
  You can generate a calendar for the month with the `month_calendar`
35
35
  method.
36
- This will use `params[:start_date]` to render the calendar.
37
36
 
38
37
  ```erb
39
- <%= month_calendar :start_date do |day| %>
40
- <%= day %>
38
+ <%= month_calendar do |date| %>
39
+ <%= date %>
41
40
  <% end %>
42
41
  ```
43
42
 
44
43
  ### Week Calendar
45
44
 
46
45
  You can generate a week calendar with the `week_calendar` method.
47
- This will use `params[:start_date]` to render the calendar.
48
46
 
49
47
  ```erb
50
- <%= week_calendar :start_date, number_of_weeks: 2 do |day| %>
51
- <%= day %>
48
+ <%= week_calendar number_of_weeks: 2 do |date| %>
49
+ <%= date %>
52
50
  <% end %>
53
51
  ```
54
52
 
@@ -57,16 +55,66 @@ Setting `number_of_weeks` is optional and defaults to 1.
57
55
  ### Custom Length Calendar
58
56
 
59
57
  You can generate calendars of any length by passing in the number of days you want to render.
60
- This will use `params[:start_date]` to render the calendar.
61
58
 
62
59
  ```erb
63
- <%= calendar :start_date, number_of_days: 4 do |day| %>
64
- <%= day %>
60
+ <%= calendar number_of_days: 4 do |date| %>
61
+ <%= date %>
65
62
  <% end %>
66
63
  ```
67
64
 
68
65
  Setting `number_of_days` is optional and defaults to 4.
69
66
 
67
+ ## Rendering Events
68
+
69
+ What's a calendar without events in it? There are two simple steps for
70
+ creating calendars with events.
71
+
72
+ The first step is to add the following to your model. We'll be using a
73
+ model called Event, but you can add this to any model or Ruby object.
74
+
75
+ We use the `has_calendar` method to tell simple_calendar how to filter
76
+ and sort the events on the different calendar days. This should be the
77
+ start date/time of your event. By default it uses `starts_at` as the
78
+ attribute name.
79
+
80
+ ```ruby
81
+ class Event < ActiveRecord::Base
82
+ extend SimpleCalendar
83
+ has_calendar
84
+
85
+ # Or set a custom attribute for simple_calendar to sort by
86
+ # has_calendar :attribute => :your_starting_time_column_name
87
+ end
88
+ ```
89
+
90
+ In your controller, query for these events and store them in an instance
91
+ variable. We'll just load up all the events for this example.
92
+
93
+ ```ruby
94
+ def index
95
+ @events = Event.all
96
+ end
97
+ ```
98
+
99
+ Then in your view, you can pass in the `events` option to render. The
100
+ events will automatically be filter out by day for you.
101
+
102
+ ```erb
103
+ <%= month_calendar events: @events do |date, events| %>
104
+ <%= date %>
105
+
106
+ <% events.each do |event| %>
107
+ <div>
108
+ <%= event.name %>
109
+ </div>
110
+ <% end %>
111
+ <% end %>
112
+ ```
113
+
114
+ If you pass in objects that don't respond to the attribute method (like
115
+ starts_at), then all the events will be yielded each day. This lets you
116
+ do custom filtering however you want.
117
+
70
118
  ## Customizing The Calendar
71
119
 
72
120
  You can change a couple of global options that will affect how the
@@ -113,10 +161,7 @@ the `content_tag` method so each of them **must** be a hash.
113
161
 
114
162
  ```ruby
115
163
 
116
- <%= calendar :start_date,
117
- table: {class: "table table-bordered"},
118
- tr: {class: "row"},
119
- td: {class: "day"}, do |day| %>
164
+ <%= calendar table: {class: "table table-bordered"}, tr: {class: "row"}, td: {class: "day"}, do |day| %>
120
165
  <% end %>
121
166
  ```
122
167
 
@@ -149,9 +194,7 @@ content_tag options. If you wish to set a class or data attributes, just
149
194
  set them as you normally would in a content_tag call.
150
195
 
151
196
  ```erb
152
- <%= month_calendar :start_date, tr: ->(start_date,
153
- current_calendar_date) { {class: "calendar-date", data: {day:
154
- current_calendar_date}} } do |day| %>
197
+ <%= month_calendar td: ->(start_date, current_calendar_date) { {class: "calendar-date", data: {day: current_calendar_date}} } do |day| %>
155
198
  <% end %>
156
199
  ```
157
200
 
@@ -162,6 +205,25 @@ This generate each day in the calendar like this:
162
205
  </td>
163
206
  ```
164
207
 
208
+ Instead of writing the lambdas inline, a cleaner approach is to write a
209
+ helper that returns a lambda. You can duplicate the following example by
210
+ adding this to your helpers
211
+
212
+ ```ruby
213
+ def month_calendar_td_options
214
+ ->(start_date, current_calendar_date) {
215
+ {class: "calendar-date", data: {day: current_calendar_date}}
216
+ }
217
+ end
218
+ ```
219
+
220
+ And then your view would use `month_calendar_td_options` as the value.
221
+
222
+ ```erb
223
+ <%= month_calendar td: month_calendar_td_options do |day| %>
224
+ <% end %>
225
+ ```
226
+
165
227
  ### Custom Header Links
166
228
 
167
229
  Each of the calendar methods will generate a header with links to the
@@ -174,8 +236,7 @@ To change these, you can pass in the `prev_link`, `header`, and
174
236
  The default `month_calendar` look like this:
175
237
 
176
238
  ```erb
177
- <%= month_calendar :start_date,
178
- prev_link: ->(range) { link_to raw("&laquo;"), param_name => range.first - 1.day },
239
+ <%= month_calendar prev_link: ->(range) { link_to raw("&laquo;"), param_name => range.first - 1.day },
179
240
  header: ->{ content_tag :span, "#{I18n.t("date.month_names")[start_date.month]} #{start_date.year}", class: "calendar-header" },
180
241
  next_link: ->(range) { link_to raw("&raquo;"), param_name => range.last + 1.day } do |day| %>
181
242
 
@@ -197,16 +258,12 @@ If you wish to disable any of these partsof the header, just pass in
197
258
  `false` and that will hide it:
198
259
 
199
260
  ```erb
200
- <%= month_calendar :start_date, header: false do |day| %>
261
+ <%= month_calendar header: false do |day| %>
201
262
  <% end %>
202
263
  ```
203
264
 
204
265
  ## TODO
205
266
 
206
- - Having an "events" option would be nice. Users can pass in all the
207
- objects and we can use it to auto-filter them so the user doesn't
208
- have to. This is what the previous version did and yielded the
209
- day's events to the block.
210
267
  - Multi-day events?
211
268
 
212
269
  ## Author
@@ -0,0 +1,126 @@
1
+ module SimpleCalendar
2
+ class Calendar
3
+ delegate :capture, :concat, :content_tag, :link_to, :params, :raw, :safe_join, to: :view_context
4
+
5
+ attr_reader :block, :events, :options, :view_context
6
+
7
+ def initialize(view_context, options={})
8
+ @view_context = view_context
9
+ @events = options.delete(:events) { [] }
10
+ @options = options
11
+ @options[:previous_link] ||= default_previous_link
12
+ @options[:header] ||= default_header
13
+ @options[:next_link] ||= default_next_link
14
+ @options[:td] ||= default_td_classes
15
+ end
16
+
17
+ def render(block)
18
+ @block = block
19
+
20
+ capture do
21
+ concat render_header
22
+ concat render_table
23
+ end
24
+ end
25
+
26
+ def render_header
27
+ capture do
28
+ content_tag :div do
29
+ concat get_option(:previous_link, param_name, date_range)
30
+ concat get_option(:header, start_date)
31
+ concat get_option(:next_link, param_name, date_range)
32
+ end
33
+ end
34
+ end
35
+
36
+ def render_table
37
+ content_tag :table, get_option(:table) do
38
+ content_tag :tbody, get_option(:tbody) do
39
+ render_weeks
40
+ end
41
+ end
42
+ end
43
+
44
+ def render_weeks
45
+ capture do
46
+ date_range.each_slice(7) do |week|
47
+ concat content_tag(:tr, render_week(week), get_option(:tr, week))
48
+ end
49
+ end
50
+ end
51
+
52
+ def render_week(week)
53
+ results = week.map do |day|
54
+ content_tag :td, get_option(:td, start_date, day) do
55
+ block.call day, events_for_date(day)
56
+ end
57
+ end
58
+ safe_join results
59
+ end
60
+
61
+ def param_name
62
+ @param_name ||= options.fetch(:param_name, :start_date)
63
+ end
64
+
65
+ def events_for_date(current_date)
66
+ if events.any? && events.first.respond_to?(:simple_calendar_start_time)
67
+ events.select do |e|
68
+ current_date == e.send(:simple_calendar_start_time).to_date
69
+ end.sort_by(&:simple_calendar_start_time)
70
+ else
71
+ events
72
+ end
73
+ end
74
+
75
+ def default_previous_link
76
+ ->(param, date_range) { link_to raw("&laquo;"), param => date_range.first - 1.day }
77
+ end
78
+
79
+ def default_header
80
+ ->(start_date) { }
81
+ end
82
+
83
+ def default_next_link
84
+ ->(param, date_range) { link_to raw("&raquo;"), param => date_range.last + 1.day }
85
+ end
86
+
87
+ def start_date
88
+ @start_date ||= (params[param_name] ||Time.zone.now).to_date
89
+ end
90
+
91
+ def date_range
92
+ @date_range ||= begin
93
+ number_of_days = options.fetch(:number_of_days, 4) - 1
94
+ start_date..(start_date + number_of_days.days)
95
+ end
96
+ end
97
+
98
+ def default_td_classes
99
+ ->(start_date, current_calendar_date) {
100
+ today = Time.zone.now.to_date
101
+ td_class = ["day"]
102
+
103
+ td_class << "today" if today == current_calendar_date
104
+ td_class << "past" if today > current_calendar_date
105
+ td_class << "future" if today < current_calendar_date
106
+ td_class << "prev-month" if start_date.month != current_calendar_date.month && current_calendar_date < start_date
107
+ td_class << "next-month" if start_date.month != current_calendar_date.month && current_calendar_date > start_date
108
+ td_class << "current-month" if start_date.month == current_calendar_date.month
109
+ td_class << "wday-#{current_calendar_date.wday.to_s}"
110
+
111
+ { class: td_class.join(" ") }
112
+ }
113
+ end
114
+
115
+ def get_option(name, *params)
116
+ option = options[name]
117
+ case option
118
+ when Hash
119
+ option
120
+ else
121
+ option.call(*params) if option.respond_to? :call
122
+ end
123
+ end
124
+ end
125
+ end
126
+
@@ -0,0 +1,16 @@
1
+ module SimpleCalendar
2
+ module ModelAdditions
3
+ def has_calendar(options={})
4
+ config = { :attribute => :starts_at }
5
+
6
+ # Override default config
7
+ config.update(options) if options.is_a?(Hash)
8
+
9
+ class_eval <<-EOV
10
+ def simple_calendar_start_time
11
+ #{config[:attribute]}
12
+ end
13
+ EOV
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module SimpleCalendar
2
+ class MonthCalendar < Calendar
3
+ def date_range
4
+ @date_range ||= start_date.beginning_of_month.beginning_of_week..start_date.end_of_month.end_of_week
5
+ end
6
+
7
+ def default_header
8
+ ->(start_date) { content_tag :span, month_name(start_date), class: "calendar-header" }
9
+ end
10
+
11
+ def month_name(start_date)
12
+ "#{I18n.t("date.month_names")[start_date.month]} #{start_date.year}"
13
+ end
14
+ end
15
+ end
16
+
@@ -1,3 +1,3 @@
1
1
  module SimpleCalendar
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,150 +1,18 @@
1
1
  module SimpleCalendar
2
2
  module ViewHelpers
3
- def month_calendar(param_name=:start_date, options={}, &block)
4
- start_date = (params[param_name] || Time.zone.now).to_date
5
-
6
- options.reverse_merge!(
7
- td: day_classes,
8
- prev_link: ->(range) { link_to raw("&laquo;"), param_name => range.first - 1.day },
9
- header: month_header,
10
- next_link: ->(range) { link_to raw("&raquo;"), param_name => range.last + 1.day },
11
- start_date: start_date,
12
- )
13
- render_calendar month_range(start_date), options, &block
14
- end
15
-
16
- def week_calendar(param_name=:start_date, options={}, &block)
17
- start_date = (params[param_name] || Time.zone.now).to_date
18
- number_of_weeks = options.fetch(:number_of_weeks, 1)
19
-
20
- options.reverse_merge!(
21
- td: day_classes,
22
- prev_link: ->(range) { link_to raw("&laquo;"), param_name => range.first - 1.day },
23
- header: false,
24
- next_link: ->(range) { link_to raw("&raquo;"), param_name => range.last + 1.day },
25
- start_date: start_date,
26
- )
27
- render_calendar week_range(start_date, number_of_weeks), options, &block
28
- end
29
-
30
- def calendar(param_name=:start_date, options={}, &block)
31
- start_date = (params[param_name] || Time.zone.now).to_date
32
- number_of_days_to_advance = options.fetch(:number_of_days, 4) - 1
33
-
34
- options.reverse_merge!(
35
- td: day_classes,
36
- prev_link: ->(range) { link_to raw("&laquo;"), param_name => range.first - 1.day },
37
- header: false,
38
- next_link: ->(range) { link_to raw("&raquo;"), param_name => range.last + 1.day },
39
- start_date: start_date,
40
- )
41
- render_calendar calendar_range(start_date, number_of_days_to_advance), options, &block
42
- end
43
-
44
- def month_range(start_date)
45
- start_date.beginning_of_month.beginning_of_week.to_date..start_date.end_of_month.end_of_week.to_date
46
- end
47
-
48
- def week_range(start_date, number_of_weeks)
49
- number_of_days_to_advance = (number_of_weeks * 7) - 1
50
- starting_day = start_date.beginning_of_week.to_date
51
- ending_day = starting_day + number_of_days_to_advance.days
52
- starting_day..ending_day
53
- end
54
-
55
- def calendar_range(start_date, number_of_days_to_advance)
56
- start_date..(start_date + number_of_days_to_advance.days)
57
- end
58
-
59
- def render_calendar(range, options, &block)
60
- raise 'SimpleCalendar requires a block' unless block_given?
61
-
62
- @block = block
63
- @options = options.reverse_merge default_options
64
- @start_date = options.fetch(:start_date)
65
-
66
- capture do
67
- concat render_header(@start_date, range)
68
- concat render_table(range)
69
- end
70
- end
71
-
72
- def render_header(start_date, range)
73
- capture do
74
- content_tag :div do
75
- concat get_options(@options[:prev_link], range)
76
- concat get_options(@options[:header], start_date)
77
- concat get_options(@options[:next_link], range)
78
- end
79
- end
80
- end
81
-
82
- def render_table(range)
83
- content_tag(:table, get_options(@options[:table])) do
84
- content_tag(:tbody) do
85
- render_weeks(range)
86
- end
87
- end
88
- end
89
-
90
-
91
- def render_weeks(range)
92
- weeks = []
93
- range.each_slice(7) do |week|
94
- weeks << content_tag(:tr, get_options(@options[:tr], week)) do
95
- render_week(week)
96
- end
97
- end
98
- safe_join weeks
3
+ def calendar(options={}, &block)
4
+ raise 'calendar requires a block' unless block_given?
5
+ SimpleCalendar::Calendar.new(self, options).render(block)
99
6
  end
100
7
 
101
- def render_week(week)
102
- results = week.map do |day|
103
- content_tag :td, get_options(@options[:td], @start_date, day) do
104
- @block.call(day)
105
- end
106
- end
107
- safe_join results
108
- end
109
-
110
- def get_options(options, *params)
111
- case options
112
- when Hash
113
- options
114
- when String
115
- send(options, *params)
116
- when Symbol
117
- send(options, *params)
118
- else
119
- options.call(*params) if options.respond_to? :call
120
- end
121
- end
122
-
123
- def default_options
124
- { table: {}, tr: {}, td: {}, }
125
- end
126
-
127
- def day_classes
128
- ->(start_date, current_calendar_date) {
129
- today = Time.zone.now.to_date
130
- td_class = ["day"]
131
-
132
- td_class << "today" if today == current_calendar_date
133
- td_class << "past" if today > current_calendar_date
134
- td_class << "future" if today < current_calendar_date
135
- td_class << "prev-month" if start_date.month != current_calendar_date.month && current_calendar_date < start_date
136
- td_class << "next-month" if start_date.month != current_calendar_date.month && current_calendar_date > start_date
137
- td_class << "current-month" if start_date.month == current_calendar_date.month
138
- td_class << "wday-#{current_calendar_date.wday.to_s}"
139
-
140
- { class: td_class.join(" ") }
141
- }
8
+ def month_calendar(options={}, &block)
9
+ raise 'month_calendar requires a block' unless block_given?
10
+ SimpleCalendar::MonthCalendar.new(self, options).render(block)
142
11
  end
143
12
 
144
- def month_header
145
- ->(start_date) {
146
- content_tag :span, "#{I18n.t("date.month_names")[start_date.month]} #{start_date.year}", class: "calendar-header"
147
- }
13
+ def week_calendar(options={}, &block)
14
+ raise 'week_calendar requires a block' unless block_given?
15
+ SimpleCalendar::WeekCalendar.new(self, options).render(block)
148
16
  end
149
17
  end
150
18
  end
@@ -0,0 +1,22 @@
1
+ module SimpleCalendar
2
+ class WeekCalendar < Calendar
3
+ def date_range
4
+ @date_range ||= begin
5
+ number_of_weeks = options.fetch(:number_of_weeks, 1)
6
+ number_of_days = (number_of_weeks * 7) - 1
7
+ starting_day = start_date.beginning_of_week.to_date
8
+ ending_day = starting_day + number_of_days.days
9
+ starting_day..ending_day
10
+ end
11
+ end
12
+
13
+ def default_previous_link
14
+ ->(param, date_range) { link_to raw("&laquo;"), param => date_range.first - 8.days }
15
+ end
16
+
17
+ def default_next_link
18
+ ->(param, date_range) { link_to raw("&raquo;"), param => date_range.last + 1.day }
19
+ end
20
+ end
21
+ end
22
+
@@ -1,3 +1,17 @@
1
+ require "simple_calendar/calendar"
2
+ require "simple_calendar/month_calendar"
3
+ require "simple_calendar/week_calendar"
4
+ require "simple_calendar/model_additions"
5
+ require "simple_calendar/railtie"
1
6
  require "simple_calendar/version"
2
7
  require "simple_calendar/view_helpers"
3
- require "simple_calendar/railtie"
8
+
9
+ module SimpleCalendar
10
+ def self.extended(model_class)
11
+ return if model_class.respond_to? :has_calendar
12
+
13
+ model_class.class_eval do
14
+ extend ModelAdditions
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_calendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-12 00:00:00.000000000 Z
11
+ date: 2014-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.0'
27
27
  description: A simple Rails 3 and Rails 4 calendar
@@ -31,15 +31,19 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
- - ".gitignore"
35
- - ".rspec"
34
+ - .gitignore
35
+ - .rspec
36
36
  - Gemfile
37
37
  - README.md
38
38
  - Rakefile
39
39
  - lib/simple_calendar.rb
40
+ - lib/simple_calendar/calendar.rb
41
+ - lib/simple_calendar/model_additions.rb
42
+ - lib/simple_calendar/month_calendar.rb
40
43
  - lib/simple_calendar/railtie.rb
41
44
  - lib/simple_calendar/version.rb
42
45
  - lib/simple_calendar/view_helpers.rb
46
+ - lib/simple_calendar/week_calendar.rb
43
47
  - simple_calendar.gemspec
44
48
  homepage: https://github.com/excid3/simple_calendar
45
49
  licenses: []
@@ -50,12 +54,12 @@ require_paths:
50
54
  - lib
51
55
  required_ruby_version: !ruby/object:Gem::Requirement
52
56
  requirements:
53
- - - ">="
57
+ - - '>='
54
58
  - !ruby/object:Gem::Version
55
59
  version: '0'
56
60
  required_rubygems_version: !ruby/object:Gem::Requirement
57
61
  requirements:
58
- - - ">="
62
+ - - '>='
59
63
  - !ruby/object:Gem::Version
60
64
  version: '0'
61
65
  requirements: []