calendar_date_select 1.12 → 1.13

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == Version 1.13
2
+ * Lots of code clean up!
3
+ * Moved test suite over to rspec
4
+ * CalendarDateSelect.default_options implemented. Use CalendarDateSelect.default_options.update(...) to set the default_options for your app.
5
+ * calendar_date_select and calendar_date_select_tag accept an :image parameter.
6
+ * Backwards compatibility hook for Rails 2.1
7
+ * RDOC!
8
+ * Don't try to focus a hidden or disabled element (closes #129 - thanks Bruno)
9
+ * Call onchange callback when clearing the calendar (closes #137 - thanks Chewi)
10
+ * Fixed issue that made :db format worthless (closes #135, thanks Andreas Zecher)
11
+ * dramatic optimization for calendar initial-rendering (thanks Yehudab, Bompus)
12
+
1
13
  == Version 1.12 ==
2
14
  * Updated for compatibility with Rails 2.2
3
15
 
data/Manifest.txt CHANGED
@@ -7,6 +7,7 @@ js_test/unit/cds_helper_methods.html
7
7
  js_test/unittest.js
8
8
  lib/calendar_date_select/calendar_date_select.rb
9
9
  lib/calendar_date_select/includes_helper.rb
10
+ lib/calendar_date_select/form_helpers.rb
10
11
  lib/calendar_date_select.rb
11
12
  Manifest.txt
12
13
  MIT-LICENSE
@@ -34,6 +35,8 @@ public/stylesheets/calendar_date_select/red.css
34
35
  public/stylesheets/calendar_date_select/silver.css
35
36
  Rakefile
36
37
  Readme.txt
37
- test/functional/calendar_date_select_test.rb
38
- test/functional/helper_methods_test.rb
39
- test/test_helper.rb
38
+ spec/
39
+ spec/calendar_date_select
40
+ spec/calendar_date_select/calendar_date_select_spec.rb
41
+ spec/calendar_date_select/form_helpers_spec.rb
42
+ spec/spec_helper.rb
@@ -1,17 +1,26 @@
1
1
  require "calendar_date_select/calendar_date_select.rb"
2
+ require "calendar_date_select/form_helpers.rb"
2
3
  require "calendar_date_select/includes_helper.rb"
3
4
 
4
5
  if Object.const_defined?(:Rails) && File.directory?(Rails.root + "/public")
5
- ActionView::Helpers::FormHelper.send(:include, CalendarDateSelect::FormHelper)
6
- ActionView::Base.send(:include, CalendarDateSelect::FormHelper)
6
+ ActionView::Helpers::FormHelper.send(:include, CalendarDateSelect::FormHelpers)
7
+ ActionView::Base.send(:include, CalendarDateSelect::FormHelpers)
7
8
  ActionView::Base.send(:include, CalendarDateSelect::IncludesHelper)
8
-
9
+
10
+ # Filthy backwards compatibility hooks... grumble
9
11
  if ([Rails::VERSION::MAJOR, Rails::VERSION::MINOR] <=> [2, 2]) == -1
10
- puts "This version of calendar date select (#{CalendarDateSelect.version}) requires Rails 2.2"
11
- puts "To use an earlier version of rails, use calendar_date_select version 1.11.x"
12
- exit
13
- end
12
+ ActionView::Helpers::InstanceTag.class_eval do
13
+ def self.new_with_backwards_compatibility(object_name, method_name, template_object, object = nil)
14
+ new(object_name, method_name, template_object, nil, object)
15
+ end
16
+ end
14
17
 
18
+ else
19
+ ActionView::Helpers::InstanceTag.class_eval do
20
+ class << self; alias new_with_backwards_compatibility new; end
21
+ end
22
+ end
23
+
15
24
  # install files
16
25
  unless File.exists?(RAILS_ROOT + '/public/javascripts/calendar_date_select/calendar_date_select.js')
17
26
  ['/public', '/public/javascripts/calendar_date_select', '/public/stylesheets/calendar_date_select', '/public/images/calendar_date_select', '/public/javascripts/calendar_date_select/locale'].each do |dir|
@@ -1,5 +1,5 @@
1
- class CalendarDateSelect
2
- VERSION = '1.12'
1
+ module CalendarDateSelect
2
+ VERSION = '1.13'
3
3
  FORMATS = {
4
4
  :natural => {
5
5
  :date => "%B %d, %Y",
@@ -11,10 +11,10 @@ class CalendarDateSelect
11
11
  :javascript_include => "format_hyphen_ampm"
12
12
  },
13
13
  :iso_date => {
14
- :date => "%Y-%m-%d",
14
+ :date => "%Y-%m-%d",
15
15
  :time => " %H:%M",
16
16
  :javascript_include => "format_iso_date"
17
- },
17
+ },
18
18
  :finnish => {
19
19
  :date => "%d.%m.%Y",
20
20
  :time => " %H:%M",
@@ -27,12 +27,12 @@ class CalendarDateSelect
27
27
  },
28
28
  :euro_24hr => {
29
29
  :date => "%d %B %Y",
30
- :time => " %H:%M",
30
+ :time => " %H:%M",
31
31
  :javascript_include => "format_euro_24hr"
32
32
  },
33
33
  :euro_24hr_ymd => {
34
34
  :date => "%Y.%m.%d",
35
- :time => " %H:%M",
35
+ :time => " %H:%M",
36
36
  :javascript_include => "format_euro_24hr_ymd"
37
37
  },
38
38
  :italian => {
@@ -42,182 +42,75 @@ class CalendarDateSelect
42
42
  },
43
43
  :db => {
44
44
  :date => "%Y-%m-%d",
45
- :time => "%H:%M",
45
+ :time => " %H:%M",
46
46
  :javascript_include => "format_db"
47
47
  }
48
48
  }
49
-
50
- cattr_accessor :image
51
- @@image = "calendar_date_select/calendar.gif"
52
-
53
- cattr_reader :format
54
- @@format = FORMATS[:natural]
55
-
56
- class << self
57
- def format=(format)
58
- raise "CalendarDateSelect: Unrecognized format specification: #{format}" unless FORMATS.has_key?(format)
59
- @@format = FORMATS[format]
60
- end
61
-
62
- def javascript_format_include
63
- @@format[:javascript_include] && "calendar_date_select/#{@@format[:javascript_include]}"
64
- end
65
-
66
- def date_format_string(time=false)
67
- @@format[:date] + ( time ? @@format[:time] : "" )
68
- end
69
-
70
- def format_date(date)
71
- if Date===date
72
- date.strftime(date_format_string(false))
73
- else
74
- date.strftime(date_format_string(true))
75
- end
76
- end
77
-
78
- def has_time?(value)
79
- /[0-9]:[0-9]{2}/.match(value.to_s)
80
- end
49
+
50
+ # Returns the default_options hash. These options are by default provided to every calendar_date_select control, unless otherwise overrided.
51
+ #
52
+ # Example:
53
+ # # At the bottom of config/environment.rb:
54
+ # CalendarDateSelect.default_options.update(
55
+ # :popup => "force",
56
+ # :month_year => "label",
57
+ # :image => "custom_calendar_picker.png"
58
+ # )
59
+ def self.default_options
60
+ @default_options ||= { :image => "calendar_date_select/calendar.gif" }
81
61
  end
82
-
83
- module FormHelper
84
- def calendar_date_select_tag( name, value = nil, options = {})
85
- calendar_options = calendar_date_select_process_options(options)
86
- value = format_time(value, calendar_options)
87
-
88
- calendar_options.delete(:format)
89
-
90
- options[:id] ||= name
91
- tag = calendar_options[:hidden] || calendar_options[:embedded] ?
92
- hidden_field_tag(name, value, options) :
93
- text_field_tag(name, value, options)
94
-
95
- calendar_date_select_output(tag, calendar_options)
96
- end
97
-
98
- def format_time(value, options = {})
99
- if value.respond_to?("strftime")
100
- if options[:format]
101
- value = value.strftime(options[:format])
102
- else
103
- if options.has_key? :time
104
- value = value.strftime(CalendarDateSelect.date_format_string(options[:time]))
105
- else
106
- value = CalendarDateSelect.format_date(value)
107
- end
108
- end
109
- end
110
- value
111
- end
112
-
113
- # extracts any options passed into calendar date select, appropriating them to either the Javascript call or the html tag.
114
- def calendar_date_select_process_options(options)
115
- calendar_options = {}
116
- callbacks = [:before_show, :before_close, :after_show, :after_close, :after_navigate]
117
- for key in [:time, :valid_date_check, :embedded, :buttons, :clear_button, :format, :year_range, :month_year, :popup, :hidden, :minute_interval] + callbacks
118
- calendar_options[key] = options.delete(key) if options.has_key?(key)
119
- end
120
-
121
- # if passing in mixed, pad it with single quotes
122
- calendar_options[:time] = "'mixed'" if calendar_options[:time].to_s=="mixed"
123
- calendar_options[:month_year] = "'#{calendar_options[:month_year]}'" if calendar_options[:month_year]
124
-
125
- # if we are forcing the popup, automatically set the readonly property on the input control.
126
- if calendar_options[:popup].to_s == "force"
127
- calendar_options[:popup] = "'force'"
128
- options[:readonly] = true
129
- end
130
-
131
- if (vdc=calendar_options.delete(:valid_date_check))
132
- if vdc.include?(";") || vdc.include?("function")
133
- throw ":valid_date_check function is missing a 'return' statement. Try something like: :valid_date_check => 'if (date > new(Date)) return true; else return false;'" unless vdc.include?("return");
134
- end
135
-
136
- vdc = "return(#{vdc})" unless vdc.include?("return")
137
- vdc = "function(date) { #{vdc} }" unless vdc.include?("function")
138
- calendar_options[:valid_date_check] = vdc
139
- end
140
-
141
- calendar_options[:popup_by] ||= "this" if calendar_options[:hidden]
142
-
143
- # surround any callbacks with a function, if not already done so
144
- for key in callbacks
145
- calendar_options[key] = "function(param) { #{calendar_options[key]} }" unless calendar_options[key].include?("function") if calendar_options[key]
146
- end
147
-
148
- calendar_options[:year_range] = format_year_range(calendar_options[:year_range] || 10)
149
- calendar_options
150
- end
151
-
152
- def calendar_date_select(object, method, options={})
153
- obj = options[:object] || instance_variable_get("@#{object}")
154
-
155
- if !options.include?(:time) && obj.class.respond_to?("columns_hash")
156
- column_type = (obj.class.columns_hash[method.to_s].type rescue nil)
157
- options[:time] = true if column_type == :datetime
158
- end
159
-
160
- use_time = options[:time]
161
-
162
- if options[:time].to_s=="mixed"
163
- use_time = false if Date===(obj.respond_to?(method) && obj.send(method))
164
- end
165
-
166
- calendar_options = calendar_date_select_process_options(options)
167
-
168
- options[:value] ||=
169
- if(obj.respond_to?(method) && obj.send(method).respond_to?(:strftime))
170
- obj.send(method).strftime(CalendarDateSelect.date_format_string(use_time))
171
- elsif obj.respond_to?("#{method}_before_type_cast")
172
- obj.send("#{method}_before_type_cast")
173
- elsif obj.respond_to?(method)
174
- obj.send(method).to_s
175
- else
176
- nil
177
- end
178
62
 
179
- tag = ActionView::Helpers::InstanceTag.new(object, method, self, options.delete(:object))
180
- calendar_date_select_output(
181
- tag.to_input_field_tag( (calendar_options[:hidden] || calendar_options[:embedded]) ? "hidden" : "text", options),
182
- calendar_options
183
- )
184
- end
185
-
186
- def calendar_date_select_output(input, calendar_options = {})
187
- out = input
188
- if calendar_options[:embedded]
189
- uniq_id = "cds_placeholder_#{(rand*100000).to_i}"
190
- # we need to be able to locate the target input element, so lets stick an invisible span tag here we can easily locate
191
- out << content_tag(:span, nil, :style => "display: none; position: absolute;", :id => uniq_id)
192
-
193
- out << javascript_tag("new CalendarDateSelect( $('#{uniq_id}').previous(), #{options_for_javascript(calendar_options)} ); ")
194
- else
195
- out << " "
196
-
197
- out << image_tag(CalendarDateSelect.image,
198
- :onclick => "new CalendarDateSelect( $(this).previous(), #{options_for_javascript(calendar_options)} );",
199
- :style => 'border:0px; cursor:pointer;')
200
- end
201
-
202
- out
203
- end
204
-
205
- private
206
- def format_year_range(year) # nodoc
207
- return year unless year.respond_to?(:first)
208
- return "[#{year.first}, #{year.last}]" unless year.first.respond_to?(:strftime)
209
- return "[#{year.first.year}, #{year.last.year}]"
63
+ # Set the picker image. Provide the image url the same way you would provide it to image_tag
64
+ def self.image=(value)
65
+ default_options[:image] = value
66
+ end
67
+
68
+ # Returns the options for the given format
69
+ #
70
+ # Example:
71
+ # CalendarDateSelect.format = :italian
72
+ # puts CalendarDateSelect.format[:date]
73
+ # => "%d/%m/%Y"
74
+ def self.format
75
+ @format ||= FORMATS[:natural]
76
+ end
77
+
78
+ # Set the format. To see a list of available formats, CalendarDateSelect::FORMATS.keys, or open lib/calendar_date_select/calendar_date_select.rb
79
+ #
80
+ # (e.g. CalendarDateSelect.format = :italian)
81
+ def self.format=(format)
82
+ raise "CalendarDateSelect: Unrecognized format specification: #{format}" unless FORMATS.has_key?(format)
83
+ @format = FORMATS[format]
84
+ end
85
+
86
+ def self.date_format_string(time = false)
87
+ format[:date] + (time ? format[:time] : "")
88
+ end
89
+
90
+ def self.format_date(date)
91
+ if date.is_a?(Date)
92
+ date.strftime(date_format_string(false))
93
+ else
94
+ date.strftime(date_format_string(true))
210
95
  end
211
96
  end
212
- end
213
97
 
98
+ def self.format_time(value, options = {})
99
+ return value unless value.respond_to?("strftime")
100
+ if options[:time]
101
+ format_date(value)
102
+ else
103
+ format_date(value.to_date)
104
+ end
105
+ end
214
106
 
215
- module ActionView
216
- module Helpers
217
- class FormBuilder
218
- def calendar_date_select(method, options = {})
219
- @template.calendar_date_select(@object_name, method, options.merge(:object => @object))
220
- end
107
+ # Detects the presence of time in a date, string
108
+ def self.has_time?(value)
109
+ case value
110
+ when DateTime, Time then true
111
+ when Date then false
112
+ else
113
+ /[0-9]:[0-9]{2}/.match(value.to_s) ? true : false
221
114
  end
222
115
  end
223
116
  end
@@ -0,0 +1,222 @@
1
+ # Various helpers available for use in your view
2
+ module CalendarDateSelect::FormHelpers
3
+
4
+ # Similar to text_field_tag, but adds a calendar picker, naturally.
5
+ #
6
+ # == Arguments
7
+ #
8
+ # +name+ - the html name of the tag
9
+ # +value+ - When specified as a string, uses value verbatim. When Date, DateTime, Time, it converts it to a string basd off the format set by CalendarDateSelect#format=
10
+ # +options+ - ...
11
+ #
12
+ # == Options
13
+ #
14
+ # === :embedded
15
+ #
16
+ # Put the calendar straight into the form, rather than using a popup type of form.
17
+ #
18
+ # <%= calendar_date_select_tag "name", "2007-01-01", :embedded => true %>
19
+ #
20
+ # === :hidden
21
+ #
22
+ # Use a hidden element instead of a text box for a pop up calendar. Not compatible with :embedded => true. You'll probably want to use an onchange callback to do something with the value.
23
+ #
24
+ # <span id='cds_value' />
25
+ # <%= calendar_date_select_tag "hidden_date_selector", "", :hidden => "true", :onchange => "$('cds_value').update($F(this));" %>
26
+ #
27
+ # === :image
28
+ #
29
+ # Specify an alternative icon to use for the date picker.
30
+ #
31
+ # To use /images/groovy.png:
32
+ #
33
+ # <%= calendar_date_select_tag "altered_image", "", :image => "groovy.png" %>
34
+ #
35
+ # === :minute_interval
36
+ #
37
+ # Specifies the minute interval used in the hour/minute selector. Default is 5.
38
+ #
39
+ # <%= calendar_date_select_tag "month_year_selector_label", "", :minute_interval => 15 %>
40
+ #
41
+ # === :month_year
42
+ #
43
+ # Customize the month and year selectors at the top of the control.
44
+ #
45
+ # Valid values:
46
+ # * "dropdowns" (default) - Use a separate dropdown control for both the month and year
47
+ # * "label" - Use static text to show the month and the year.
48
+ #
49
+ # <%= calendar_date_select_tag "month_year_selector_label", "", :month_year => "label" %>
50
+ #
51
+ # === :popup => 'force'
52
+ #
53
+ # Forces the user to use the popup calendar by making it's text-box read-only and causing calendar_date_select to override it's default behavior of not allowing selection of a date on a target element that is read-only.
54
+ #
55
+ # <%= calendar_date_select_tag "name", "2007-01-01", :popup => "force" %>
56
+ #
57
+ # === :time
58
+ #
59
+ # Show time in the controls. There's three options:
60
+ #
61
+ # * +true+ - show an hour/minute selector.
62
+ # * +false+ - don't show an hour/minute selector.
63
+ # * +"mixed"+ - Show an hour/minute selector, but include a "all day" option - allowing them to choose whether or not to specify a time.
64
+ #
65
+ # === :year_range
66
+ #
67
+ # Limit the year range. You can pass in an array or range of ruby Date/Time objects or FixNum's.
68
+ #
69
+ # <%= calendar_date_select_tag "e_date", nil, :year_range => 10.years.ago..0.years.from_now %>
70
+ # <%= calendar_date_select_tag "e_date", nil, :year_range => [0.years.ago, 10.years.from_now] %>
71
+ # <%= calendar_date_select_tag "e_date", nil, :year_range => 2000..2007 %>
72
+ # <%= calendar_date_select_tag "e_date", nil, :year_range => [2000, 2007] %>
73
+ #
74
+ # == CALLBACKS
75
+ #
76
+ # The following callbacks are available:
77
+ #
78
+ # * before_show / after_show
79
+ # * before_close / after_close
80
+ # * after_navigate - Called when navigating to a different month. Passes first parameter as a date object refering to the current month viewed
81
+ # * onchange - Called when the form input value changes
82
+ #
83
+ # <%= calendar_date_select_tag "event_demo", "",
84
+ # :before_show => "log('Calendar Showing');" ,
85
+ # :after_show => "log('Calendar Shown');" ,
86
+ # :before_close => "log('Calendar closing');" ,
87
+ # :after_close => "log('Calendar closed');",
88
+ # :after_navigate => "log('Current month is ' + (param.getMonth()+1) + '/' + (param.getFullYear()));",
89
+ # :onchange => "log('value changed to - ' + $F(this));"
90
+ #
91
+ # }}}
92
+ #
93
+ # All callbacks are executed within the context of the target input element. If you'd like to access the CalendarDateSelect object itself, you can access it via "this.calendar_date_select".
94
+ #
95
+ # For example:
96
+ #
97
+ # <%= calendar_date_select_tag "event_demo", "", :after_navigate => "alert('The current selected month is ' + this.calendar_date_select.selected_date.getMonth());" ,
98
+ def calendar_date_select_tag( name, value = nil, options = {})
99
+ options, javascript_options = calendar_date_select_process_options(options)
100
+ value = CalendarDateSelect.format_time(value, javascript_options)
101
+
102
+ javascript_options.delete(:format)
103
+
104
+ options[:id] ||= name
105
+ tag = javascript_options[:hidden] || javascript_options[:embedded] ?
106
+ hidden_field_tag(name, value, options) :
107
+ text_field_tag(name, value, options)
108
+
109
+ calendar_date_select_output(tag, options, javascript_options)
110
+ end
111
+
112
+ # Similar to the difference between +text_field_tag+ and +text_field+, this method behaves like +text_field+
113
+ #
114
+ # It receives the same options as +calendar_date_select_tag+. Need for time selection is automatically detected by checking the corresponding column meta information of Model#columns_hash
115
+ def calendar_date_select(object, method, options={})
116
+ obj = options[:object] || instance_variable_get("@#{object}")
117
+
118
+ if !options.include?(:time) && obj.class.respond_to?("columns_hash")
119
+ column_type = (obj.class.columns_hash[method.to_s].type rescue nil)
120
+ options[:time] = true if column_type == :datetime
121
+ end
122
+
123
+ use_time = options[:time]
124
+
125
+ if options[:time].to_s=="mixed"
126
+ use_time = false if Date===(obj.respond_to?(method) && obj.send(method))
127
+ end
128
+
129
+ options, javascript_options = calendar_date_select_process_options(options)
130
+
131
+ options[:value] ||=
132
+ if(obj.respond_to?(method) && obj.send(method).respond_to?(:strftime))
133
+ obj.send(method).strftime(CalendarDateSelect.date_format_string(use_time))
134
+ elsif obj.respond_to?("#{method}_before_type_cast")
135
+ obj.send("#{method}_before_type_cast")
136
+ elsif obj.respond_to?(method)
137
+ obj.send(method).to_s
138
+ else
139
+ nil
140
+ end
141
+
142
+ tag = ActionView::Helpers::InstanceTag.new_with_backwards_compatibility(object, method, self, options.delete(:object))
143
+ calendar_date_select_output(
144
+ tag.to_input_field_tag( (javascript_options[:hidden] || javascript_options[:embedded]) ? "hidden" : "text", options),
145
+ options,
146
+ javascript_options
147
+ )
148
+ end
149
+
150
+ private
151
+ # extracts any options passed into calendar date select, appropriating them to either the Javascript call or the html tag.
152
+ def calendar_date_select_process_options(options)
153
+ options, javascript_options = CalendarDateSelect.default_options.merge(options), {}
154
+ callbacks = [:before_show, :before_close, :after_show, :after_close, :after_navigate]
155
+ for key in [:time, :valid_date_check, :embedded, :buttons, :clear_button, :format, :year_range, :month_year, :popup, :hidden, :minute_interval] + callbacks
156
+ javascript_options[key] = options.delete(key) if options.has_key?(key)
157
+ end
158
+
159
+ # if passing in mixed, pad it with single quotes
160
+ javascript_options[:time] = "'mixed'" if javascript_options[:time].to_s=="mixed"
161
+ javascript_options[:month_year] = "'#{javascript_options[:month_year]}'" if javascript_options[:month_year]
162
+
163
+ # if we are forcing the popup, automatically set the readonly property on the input control.
164
+ if javascript_options[:popup].to_s == "force"
165
+ javascript_options[:popup] = "'force'"
166
+ options[:readonly] = true
167
+ end
168
+
169
+ if (vdc=javascript_options.delete(:valid_date_check))
170
+ if vdc.include?(";") || vdc.include?("function")
171
+ raise ArgumentError, ":valid_date_check function is missing a 'return' statement. Try something like: :valid_date_check => 'if (date > new(Date)) return true; else return false;'" unless vdc.include?("return");
172
+ end
173
+
174
+ vdc = "return(#{vdc})" unless vdc.include?("return")
175
+ vdc = "function(date) { #{vdc} }" unless vdc.include?("function")
176
+ javascript_options[:valid_date_check] = vdc
177
+ end
178
+
179
+ javascript_options[:popup_by] ||= "this" if javascript_options[:hidden]
180
+
181
+ # surround any callbacks with a function, if not already done so
182
+ for key in callbacks
183
+ javascript_options[key] = "function(param) { #{javascript_options[key]} }" unless javascript_options[key].include?("function") if javascript_options[key]
184
+ end
185
+
186
+ javascript_options[:year_range] = format_year_range(javascript_options[:year_range] || 10)
187
+ [options, javascript_options]
188
+ end
189
+
190
+ def calendar_date_select_output(input, options = {}, javascript_options = {})
191
+ out = input
192
+ if javascript_options[:embedded]
193
+ uniq_id = "cds_placeholder_#{(rand*100000).to_i}"
194
+ # we need to be able to locate the target input element, so lets stick an invisible span tag here we can easily locate
195
+ out << content_tag(:span, nil, :style => "display: none; position: absolute;", :id => uniq_id)
196
+ out << javascript_tag("new CalendarDateSelect( $('#{uniq_id}').previous(), #{options_for_javascript(javascript_options)} ); ")
197
+ else
198
+ out << " "
199
+ out << image_tag(options[:image],
200
+ :onclick => "new CalendarDateSelect( $(this).previous(), #{options_for_javascript(javascript_options)} );",
201
+ :style => 'border:0px; cursor:pointer;')
202
+ end
203
+ out
204
+ end
205
+
206
+ def format_year_range(year) # nodoc
207
+ return year unless year.respond_to?(:first)
208
+ return "[#{year.first}, #{year.last}]" unless year.first.respond_to?(:strftime)
209
+ return "[#{year.first.year}, #{year.last.year}]"
210
+ end
211
+ end
212
+
213
+ # Helper method for form builders
214
+ module ActionView
215
+ module Helpers
216
+ class FormBuilder
217
+ def calendar_date_select(method, options = {})
218
+ @template.calendar_date_select(@object_name, method, options.merge(:object => @object))
219
+ end
220
+ end
221
+ end
222
+ end
@@ -1,38 +1,29 @@
1
- class CalendarDateSelect
2
- module IncludesHelper
3
- def calendar_date_select_stylesheets(options = {})
4
- options.assert_valid_keys(:style, :format, :locale)
5
-
6
- style = options[:style]
7
- cds_css_file = style ? "calendar_date_select/#{style}" : "calendar_date_select/default"
8
- return cds_css_file
9
- end
10
-
11
- def calendar_date_select_javascripts(options = {})
12
- options.assert_valid_keys(:style, :format, :locale)
13
-
14
- style = options[:style]
15
- locale = options[:locale]
16
- cds_css_file = style ? "calendar_date_select/#{style}" : "calendar_date_select/default"
17
-
18
- output = []
19
- output << "calendar_date_select/calendar_date_select"
20
- output << "calendar_date_select/locale/#{locale}" if locale
21
- output << CalendarDateSelect.javascript_format_include if CalendarDateSelect.javascript_format_include
22
- return output
23
- end
1
+ module CalendarDateSelect::IncludesHelper
2
+ # returns the selected calendar_date_select stylesheet (not an array)
3
+ def calendar_date_select_stylesheets(options = {})
4
+ options.assert_valid_keys(:style)
5
+ "calendar_date_select/#{options[:style] || "default"}"
6
+ end
24
7
 
25
- def calendar_date_select_includes(*args)
26
- return "" if @cds_already_included
27
- @cds_already_included=true
28
-
29
- options = (Hash === args.last) ? args.pop : {}
30
- options.assert_valid_keys(:style, :format, :locale)
31
- options[:style] ||= args.shift
8
+ # returns an array of javascripts needed for the selected locale, date_format, and calendar control itself.
9
+ def calendar_date_select_javascripts(options = {})
10
+ options.assert_valid_keys(:format, :locale)
11
+ files = ["calendar_date_select/calendar_date_select"]
12
+ files << "calendar_date_select/locale/#{options[:locale]}" if options[:locale]
13
+ files << "calendar_date_select/#{CalendarDateSelect.format[:javascript_include]}" if CalendarDateSelect.format[:javascript_include]
14
+ files
15
+ end
32
16
 
33
- js = javascript_include_tag(*calendar_date_select_javascripts(options))
34
- css = stylesheet_link_tag(*calendar_date_select_stylesheets(options))
35
- "#{js}\n#{css}\n"
36
- end
17
+ # returns html necessary to load javascript and css to make calendar_date_select work
18
+ def calendar_date_select_includes(*args)
19
+ return "" if @cds_already_included
20
+ @cds_already_included=true
21
+
22
+ options = (Hash === args.last) ? args.pop : {}
23
+ options.assert_valid_keys(:style, :format, :locale)
24
+ options[:style] ||= args.shift
25
+
26
+ javascript_include_tag(*calendar_date_select_javascripts(:locale => options[:locale], :format => options[:format])) + "\n" +
27
+ stylesheet_link_tag(*calendar_date_select_stylesheets(:style => options[:style])) + "\n"
37
28
  end
38
29
  end
@@ -1,4 +1,4 @@
1
- // CalendarDateSelect version 1.12 - a prototype based date picker
1
+ // CalendarDateSelect version 1.13 - a prototype based date picker
2
2
  // Questions, comments, bugs? - see the project page: http://code.google.com/p/calendardateselect
3
3
  if (typeof Prototype == 'undefined') alert("CalendarDateSelect Error: Prototype could not be found. Please make sure that your application's layout includes prototype.js (.g. <%= javascript_include_tag :defaults %>) *before* it includes calendar_date_select.js (.g. <%= calendar_date_select_includes %>).");
4
4
  if (Prototype.Version < "1.6") alert("Prototype 1.6.0 is required. If using earlier version of prototype, please use calendar_date_select version 1.8.3");
@@ -15,9 +15,8 @@ Element.addMethods({
15
15
  Element.buildAndAppend = function(type, options, style)
16
16
  {
17
17
  var e = $(document.createElement(type));
18
- $H(options).each(function(pair) { eval("e." + pair.key + " = pair.value" ); });
19
- if (style)
20
- $H(style).each(function(pair) { eval("e.style." + pair.key + " = pair.value" ); });
18
+ $H(options).each(function(pair) { e[pair.key] = pair.value });
19
+ if (style) e.setStyle(style);
21
20
  return e;
22
21
  };
23
22
  nil = null;
@@ -345,9 +344,11 @@ CalendarDateSelect.prototype = {
345
344
  updateFooter:function(text) { if (!text) text = this.dateString(); this.footer_div.purgeChildren(); this.footer_div.build("span", {innerHTML: text }); },
346
345
  clearDate:function() {
347
346
  if ((this.target_element.disabled || this.target_element.readOnly) && this.options.get("popup") != "force") return false;
347
+ var last_value = this.target_element.value;
348
348
  this.target_element.value = "";
349
349
  this.clearSelectedClass();
350
350
  this.updateFooter('&#160;');
351
+ if (last_value!=this.target_element.value) this.callback("onchange");
351
352
  },
352
353
  updateSelectedDate:function(partsOrElement, via_click) {
353
354
  var parts = $H(partsOrElement);
@@ -429,7 +430,7 @@ CalendarDateSelect.prototype = {
429
430
  Event.stopObserving(document, "keypress", this.keyPress_handler);
430
431
  this.calendar_div.remove(); this.closed = true;
431
432
  if (this.iframe) this.iframe.remove();
432
- if (this.target_element.type!="hidden") this.target_element.focus();
433
+ if (this.target_element.type != "hidden" && ! this.target_element.disabled) this.target_element.focus();
433
434
  this.callback("after_close");
434
435
  },
435
436
  closeIfClickedOut: function(e) {
@@ -6,5 +6,6 @@ Date.first_day_of_week = 1;
6
6
  _translations = {
7
7
  "OK": "OK",
8
8
  "Now": "Jetzt",
9
- "Today": "Heute"
9
+ "Today": "Heute",
10
+ "Clear": "Löschen"
10
11
  }
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe CalendarDateSelect do
4
+ it "should detect presence of time in a string" do
5
+ CalendarDateSelect.has_time?("January 7, 2007").should == false
6
+ CalendarDateSelect.has_time?("January 7, 2007 5:50pm").should == true
7
+ CalendarDateSelect.has_time?("January 7, 2007 5:50 pm").should == true
8
+ CalendarDateSelect.has_time?("January 7, 2007 16:30 pm").should == true
9
+
10
+ CalendarDateSelect.has_time?(Date.parse("January 7, 2007 3:00 pm")).should == false
11
+ CalendarDateSelect.has_time?(Time.parse("January 7, 2007 3:00 pm")).should == true
12
+ CalendarDateSelect.has_time?(DateTime.parse("January 7, 2007 3:00 pm")).should == true
13
+ end
14
+ end
@@ -0,0 +1,156 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe CalendarDateSelect::FormHelpers do
4
+ include ActionView::Helpers::FormHelper
5
+ include ActionView::Helpers::JavaScriptHelper
6
+ include ActionView::Helpers::AssetTagHelper
7
+ include ActionView::Helpers::TagHelper
8
+ include ActionView::Helpers::FormTagHelper
9
+
10
+ include CalendarDateSelect::FormHelpers
11
+
12
+ before(:each) do
13
+ @controller = ActionController::Base.new
14
+ @request = OpenStruct.new
15
+ @controller.request = @request
16
+
17
+ @model = OpenStruct.new
18
+ end
19
+
20
+ describe "mixed mode" do
21
+ it "should not output a time when the value is a Date" do
22
+ @model.start_datetime = Date.parse("January 2, 2007")
23
+ output = calendar_date_select(:model, :start_datetime, :time => "mixed")
24
+ output.should_not match(/12:00 AM/)
25
+ end
26
+
27
+ it "should output a time when the value is a Time" do
28
+ @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
29
+ output = calendar_date_select(:model, :start_datetime, :time => "mixed")
30
+ output.should match(/12:00 AM/)
31
+ end
32
+ end
33
+
34
+ it "should render a time when time is passed as 'true'" do
35
+ @model.start_datetime = Date.parse("January 2, 2007")
36
+ output = calendar_date_select(:model, :start_datetime, :time => "true")
37
+ output.should match(/12:00 AM/)
38
+ end
39
+
40
+ it "should time_false__model_returns_time__should_render_without_time" do
41
+ @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
42
+ output = calendar_date_select(:model, :start_datetime)
43
+ output.should_not match(/12:00 AM/)
44
+ end
45
+
46
+ it "should _nil_model__shouldnt_populate_value" do
47
+ @model = nil
48
+ output = calendar_date_select(:model, :start_datetime)
49
+
50
+ output.should_not match(/value/)
51
+ end
52
+
53
+ it "should _vdc__should_auto_format_function" do
54
+ @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
55
+ output = calendar_date_select(:model,
56
+ :start_datetime,
57
+ :valid_date_check => "date < new Date()"
58
+ )
59
+ output.should include("valid_date_check:function(date) { return(date &lt; new Date()) }")
60
+
61
+ output = calendar_date_select(:model,
62
+ :start_datetime,
63
+ :valid_date_check => "return(date < new Date())"
64
+ )
65
+ output.should include("valid_date_check:function(date) { return(date &lt; new Date()) }")
66
+ output = calendar_date_select(:model,
67
+ :start_datetime,
68
+ :valid_date_check => "function(p) { return(date < new Date()) }"
69
+ )
70
+ output.should include("valid_date_check:function(p) { return(date &lt; new Date()) }")
71
+ end
72
+
73
+ it "should raise an error if the valid_date_check function is missing a return statement" do
74
+ message = ":valid_date_check function is missing a 'return' statement. Try something like: :valid_date_check => 'if (date > new(Date)) return true; else return false;'"
75
+ lambda {
76
+ output = calendar_date_select(:model,
77
+ :start_datetime,
78
+ :valid_date_check => "date = 5; date < new Date());"
79
+ )
80
+ }.should raise_error(ArgumentError, message)
81
+
82
+ lambda {
83
+ output = calendar_date_select(:model,
84
+ :start_datetime,
85
+ :valid_date_check => "function(p) { date = 5; date < new Date()); }"
86
+ )
87
+ }.should raise_error(ArgumentError, message)
88
+ end
89
+
90
+ it "should render the year_range argument correctly" do
91
+ output = calendar_date_select(:model, :start_datetime)
92
+ output.should include("year_range:10")
93
+ output = calendar_date_select(:model, :start_datetime, :year_range => 2000..2010)
94
+ output.should include("year_range:[2000, 2010]")
95
+ output = calendar_date_select(:model, :start_datetime, :year_range => (15.years.ago..5.years.ago))
96
+ output.should include("year_range:[#{15.years.ago.year}, #{5.years.ago.year}]")
97
+ end
98
+
99
+ it "should disregard the :object parameter when nil" do
100
+ @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
101
+ output = calendar_date_select(:model, :start_datetime, :time => true, :object => nil)
102
+ output.should include(CalendarDateSelect.format_date(@model.start_datetime))
103
+ end
104
+
105
+ it "should regard :object parameter" do
106
+ @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
107
+ output = calendar_date_select(:lame_o, :start_datetime, :time => true, :object => @model)
108
+ output.should include(CalendarDateSelect.format_date(@model.start_datetime))
109
+ end
110
+
111
+ it "should respect parameters provided in default_options" do
112
+ new_options = CalendarDateSelect.default_options.merge(:popup => "force")
113
+ CalendarDateSelect.stub!(:default_options).and_return(new_options)
114
+ calendar_date_select_tag(:name, "").should include("popup:'force'")
115
+ end
116
+
117
+ it "should respect the :image option" do
118
+ output = calendar_date_select_tag(:name, "Some String", :image => "boogy.png")
119
+ output.should include("boogy.png")
120
+ end
121
+
122
+ it "should not pass the :image option as a javascript option" do
123
+ output = calendar_date_select_tag(:name, "Some String", :image => "boogy.png")
124
+ output.should_not include("image:")
125
+ end
126
+
127
+ describe "calendar_date_select_tag" do
128
+ it "should use the string verbatim when provided" do
129
+ output = calendar_date_select_tag(:name, "Some String")
130
+
131
+ output.should include("Some String")
132
+ end
133
+
134
+ it "should not render the time when time is false (or nil)" do
135
+ time = Time.parse("January 2, 2007 12:01:23 AM")
136
+ output = calendar_date_select_tag(:name, time, :time => false)
137
+
138
+ output.should_not match(/12:01 AM/)
139
+ output.should include(CalendarDateSelect.format_date(time.to_date))
140
+ end
141
+
142
+ it "should render the time when :time => true" do
143
+ time = Time.parse("January 2, 2007 12:01:23 AM")
144
+ output = calendar_date_select_tag(:name, time, :time => true)
145
+
146
+ output.should include(CalendarDateSelect.format_date(time))
147
+ end
148
+
149
+ it "should render the time when :time => 'mixed'" do
150
+ time = Time.parse("January 2, 2007 12:01:23 AM")
151
+ output = calendar_date_select_tag(:name, time, :time => 'mixed')
152
+
153
+ output.should include(CalendarDateSelect.format_date(time))
154
+ end
155
+ end
156
+ end
@@ -1,6 +1,9 @@
1
1
  require "rubygems"
2
2
 
3
- require 'test/unit'
3
+ require 'spec'
4
+
5
+ gem 'activesupport', ">= 2.2.0"
6
+ gem 'actionpack', ">= 2.2.0"
4
7
 
5
8
  require 'active_support'
6
9
  require 'action_pack'
@@ -9,10 +12,14 @@ require 'action_view'
9
12
 
10
13
  require 'ostruct'
11
14
 
15
+ ActionView::Helpers::InstanceTag.class_eval do
16
+ class << self; alias new_with_backwards_compatibility new; end
17
+ end
18
+
12
19
  $: << (File.dirname(__FILE__) + "/../lib")
13
20
  require "calendar_date_select"
14
21
 
15
- class Object
22
+ class String
16
23
  def to_regexp
17
24
  is_a?(Regexp) ? self : Regexp.new(Regexp.escape(self.to_s))
18
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calendar_date_select
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.12"
4
+ version: "1.13"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Harper
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-29 00:00:00 -07:00
12
+ date: 2008-11-30 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -43,6 +43,7 @@ files:
43
43
  - js_test/unittest.js
44
44
  - lib/calendar_date_select/calendar_date_select.rb
45
45
  - lib/calendar_date_select/includes_helper.rb
46
+ - lib/calendar_date_select/form_helpers.rb
46
47
  - lib/calendar_date_select.rb
47
48
  - Manifest.txt
48
49
  - MIT-LICENSE
@@ -70,9 +71,11 @@ files:
70
71
  - public/stylesheets/calendar_date_select/silver.css
71
72
  - Rakefile
72
73
  - Readme.txt
73
- - test/functional/calendar_date_select_test.rb
74
- - test/functional/helper_methods_test.rb
75
- - test/test_helper.rb
74
+ - spec/
75
+ - spec/calendar_date_select
76
+ - spec/calendar_date_select/calendar_date_select_spec.rb
77
+ - spec/calendar_date_select/form_helpers_spec.rb
78
+ - spec/spec_helper.rb
76
79
  has_rdoc: true
77
80
  homepage: http://code.google.com/p/calendardateselect/
78
81
  post_install_message:
@@ -96,9 +99,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
99
  requirements: []
97
100
 
98
101
  rubyforge_project: calendar_date_select
99
- rubygems_version: 1.3.0
102
+ rubygems_version: 1.3.1
100
103
  signing_key:
101
104
  specification_version: 2
102
105
  summary: ""
103
- test_files:
104
- - test/test_helper.rb
106
+ test_files: []
107
+
@@ -1,157 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
-
3
- class HelperMethodsTest < Test::Unit::TestCase
4
- include ActionView::Helpers::FormHelper
5
- include ActionView::Helpers::JavaScriptHelper
6
- include ActionView::Helpers::AssetTagHelper
7
- include ActionView::Helpers::TagHelper
8
- include ActionView::Helpers::FormTagHelper
9
-
10
- include CalendarDateSelect::FormHelper
11
-
12
- def setup
13
- @controller = ActionController::Base.new
14
- @request = OpenStruct.new
15
- @controller.request = @request
16
-
17
- @model = OpenStruct.new
18
- end
19
-
20
- def test_mixed_time__model_returns_date__should_render_without_time
21
- @model.start_datetime = Date.parse("January 2, 2007")
22
- output = calendar_date_select(:model, :start_datetime, :time => "mixed")
23
- assert_no_match(/12:00 AM/, output, "Shouldn't have outputted a time")
24
- end
25
-
26
- def test_mixed_time__model_returns_time__should_render_with_time
27
- @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
28
- output = calendar_date_select(:model, :start_datetime, :time => "mixed")
29
- assert_match(/12:00 AM/, output, "Should have outputted a time")
30
- end
31
-
32
- def test_time_true__model_returns_date__should_render_with_time
33
- @model.start_datetime = Date.parse("January 2, 2007")
34
- output = calendar_date_select(:model, :start_datetime, :time => "true")
35
- assert_match(/12:00 AM/, output, "Should have outputted a time")
36
- end
37
-
38
- def test_time_false__model_returns_time__should_render_without_time
39
- @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
40
- output = calendar_date_select(:model, :start_datetime)
41
- assert_no_match(/12:00 AM/, output, "Shouldn't have outputted a time")
42
- end
43
-
44
- def test__nil_model__shouldnt_populate_value
45
- @model = nil
46
- output = calendar_date_select(:model, :start_datetime)
47
-
48
- assert_no_match(/value/, output)
49
- end
50
-
51
- def test__vdc__should_auto_format_function
52
- @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
53
- output = calendar_date_select(:model,
54
- :start_datetime,
55
- :valid_date_check => "date < new Date()"
56
- )
57
- assert_match("valid_date_check:function(date) { return(date &lt; new Date()) }", output)
58
-
59
- output = calendar_date_select(:model,
60
- :start_datetime,
61
- :valid_date_check => "return(date < new Date())"
62
- )
63
- assert_match("valid_date_check:function(date) { return(date &lt; new Date()) }", output)
64
- output = calendar_date_select(:model,
65
- :start_datetime,
66
- :valid_date_check => "function(p) { return(date < new Date()) }"
67
- )
68
- assert_match("valid_date_check:function(p) { return(date &lt; new Date()) }", output)
69
- end
70
-
71
- def test__vdc__excluded_return__should_raise_error
72
- throw_message = ":valid_date_check function is missing a 'return' statement. Try something like: :valid_date_check => 'if (date > new(Date)) return true; else return false;'"
73
- assert_throws throw_message.to_sym do
74
- output = calendar_date_select(:model,
75
- :start_datetime,
76
- :valid_date_check => "date = 5; date < new Date());"
77
- )
78
- end
79
-
80
- assert_throws throw_message.to_sym do
81
- output = calendar_date_select(:model,
82
- :start_datetime,
83
- :valid_date_check => "function(p) { date = 5; date < new Date()); }"
84
- )
85
- end
86
- end
87
-
88
- def test__year_range__formats_correctly
89
- output = calendar_date_select(:model, :start_datetime)
90
- assert_match("year_range:10", output)
91
- output = calendar_date_select(:model, :start_datetime, :year_range => 2000..2010)
92
- assert_match("year_range:[2000, 2010]", output)
93
- output = calendar_date_select(:model, :start_datetime, :year_range => (15.years.ago..5.years.ago))
94
- assert_match("year_range:[#{15.years.ago.year}, #{5.years.ago.year}]", output)
95
- end
96
-
97
- def test__tag__formats_text_correctly_string
98
- time = "January 2, 2007 12:01:23 AM"
99
- output = calendar_date_select_tag(:name, time)
100
-
101
- assert_match(time, output, "Should have outputted a correctly formatted time")
102
- end
103
-
104
- def test__tag__formats_text_correctly_date
105
- time = Date.new(2007, 01, 02)
106
- output = calendar_date_select_tag(:name, time)
107
-
108
- assert_no_match(/12:01 AM/, output, "Should not have outputted a time")
109
- assert_match(CalendarDateSelect.format_date(time), output, "Should have outputted a correctly formatted time")
110
- end
111
-
112
- def test__tag__formats_text_correctly_time
113
- time = Time.parse("January 2, 2007 12:01:23 AM")
114
- output = calendar_date_select_tag(:name, time)
115
-
116
- assert_match(CalendarDateSelect.format_date(time), output, "Should have outputted a correctly formatted time")
117
- end
118
-
119
- def test__tag__formats_text_correctly_with_time_option
120
- time = Time.parse("January 2, 2007 12:01:23 AM")
121
- output = calendar_date_select_tag(:name, time, :time => true)
122
-
123
- assert_match(CalendarDateSelect.format_date(time), output, "Should have outputted a correctly formatted time")
124
- end
125
-
126
- def test__tag__formats_text_correctly_with_mixed_option
127
- time = Time.parse("January 2, 2007 12:01:23 AM")
128
- output = calendar_date_select_tag(:name, time, :time => 'mixed')
129
-
130
- assert_match(CalendarDateSelect.format_date(time), output, "Should have outputted a correctly formatted time")
131
- end
132
-
133
- def test__tag__formats_text_correctly_time_as_date
134
- time = Time.parse("January 2, 2007 12:01:23 AM")
135
- output = calendar_date_select_tag(:name, time, :time => false)
136
-
137
- assert_no_match(/12:01 AM/, output, "Should not have outputted a time")
138
- assert_match(time.strftime(CalendarDateSelect.date_format_string(false)), output, "Should have outputted a correctly formatted time")
139
- end
140
-
141
- def test__tag__formats_text_correctly_time_with_format
142
- time = Time.parse("January 2, 2007 12:01:00 AM")
143
- output = calendar_date_select_tag(:name, time, :format => "%Y-%m-%d")
144
-
145
- assert_no_match(/12:01 AM/, output, "Should not have outputted a time")
146
- assert_match('2007-01-02', output, "Should have outputted a correctly formatted time")
147
- end
148
-
149
- def test__nil_object_option__should_disregard
150
- @model.start_datetime = Time.parse("January 2, 2007 12:00 AM")
151
- output = calendar_date_select(:model, :start_datetime, :time => true, :object => nil)
152
- assert_match(CalendarDateSelect.format_date(@model.start_datetime), output, "Should have outputted a time")
153
- end
154
-
155
- end
156
-
157
-
@@ -1,15 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
-
3
- class HelperMethodsTest < Test::Unit::TestCase
4
- def setup
5
-
6
- end
7
-
8
- def test_has_time
9
- assert( ! CalendarDateSelect.has_time?("January 7, 2007"))
10
- assert(CalendarDateSelect.has_time?("January 7, 2007 5:50pm"))
11
- assert(CalendarDateSelect.has_time?("January 7, 2007 5:50 pm"))
12
- assert(CalendarDateSelect.has_time?("January 7, 2007 16:30 pm"))
13
- end
14
-
15
- end