rd_unobtrusive_date_picker 0.1.0
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/MIT-LICENSE +19 -0
- data/Manifest +45 -0
- data/README.rdoc +165 -0
- data/Rakefile +29 -0
- data/about.yml +7 -0
- data/init.rb +8 -0
- data/install.rb +14 -0
- data/lib/12_hour_time.rb +102 -0
- data/lib/unobtrusive_date_picker.rb +407 -0
- data/public/images/backstripes.gif +0 -0
- data/public/images/bg_header.jpg +0 -0
- data/public/images/bullet1.gif +0 -0
- data/public/images/bullet2.gif +0 -0
- data/public/images/cal.gif +0 -0
- data/public/images/gradient-e5e5e5-ffffff.gif +0 -0
- data/public/javascripts/datepicker.js +1445 -0
- data/public/javascripts/lang/af.js +40 -0
- data/public/javascripts/lang/ar.js +50 -0
- data/public/javascripts/lang/de.js +40 -0
- data/public/javascripts/lang/du.js +40 -0
- data/public/javascripts/lang/en.js +42 -0
- data/public/javascripts/lang/es.js +41 -0
- data/public/javascripts/lang/fi.js +40 -0
- data/public/javascripts/lang/fr.js +44 -0
- data/public/javascripts/lang/gr.js +40 -0
- data/public/javascripts/lang/he.js +49 -0
- data/public/javascripts/lang/it.js +13 -0
- data/public/javascripts/lang/nl.js +40 -0
- data/public/javascripts/lang/no.js +40 -0
- data/public/javascripts/lang/pt.js +50 -0
- data/public/javascripts/lang/ro.js +40 -0
- data/public/javascripts/lang/ru.js +40 -0
- data/public/javascripts/lang/sp.js +40 -0
- data/public/javascripts/lang/sv.js +41 -0
- data/public/javascripts/lang/ua.js +40 -0
- data/public/stylesheets/datepicker.css +263 -0
- data/spec/date_picker_tag_spec.rb +122 -0
- data/spec/date_picker_text_field_spec.rb +54 -0
- data/spec/datepicker_html_class_options_spec.rb +281 -0
- data/spec/spec.opts +12 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/tag_matcher.rb +142 -0
- data/spec/unobtrusive_date_picker_spec.rb +129 -0
- data/tasks/datepicker_tasks.rake +17 -0
- data/uninstall.rb +12 -0
- data/unobtrusive_date_picker.gemspec +30 -0
- metadata +116 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2007 Brian J. Landau, <brianjlandau@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
MIT-LICENSE
|
2
|
+
Manifest
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
about.yml
|
6
|
+
init.rb
|
7
|
+
install.rb
|
8
|
+
lib/12_hour_time.rb
|
9
|
+
lib/unobtrusive_date_picker.rb
|
10
|
+
public/images/backstripes.gif
|
11
|
+
public/images/bg_header.jpg
|
12
|
+
public/images/bullet1.gif
|
13
|
+
public/images/bullet2.gif
|
14
|
+
public/images/cal.gif
|
15
|
+
public/images/gradient-e5e5e5-ffffff.gif
|
16
|
+
public/javascripts/datepicker.js
|
17
|
+
public/javascripts/lang/af.js
|
18
|
+
public/javascripts/lang/ar.js
|
19
|
+
public/javascripts/lang/de.js
|
20
|
+
public/javascripts/lang/du.js
|
21
|
+
public/javascripts/lang/en.js
|
22
|
+
public/javascripts/lang/es.js
|
23
|
+
public/javascripts/lang/fi.js
|
24
|
+
public/javascripts/lang/fr.js
|
25
|
+
public/javascripts/lang/gr.js
|
26
|
+
public/javascripts/lang/he.js
|
27
|
+
public/javascripts/lang/it.js
|
28
|
+
public/javascripts/lang/nl.js
|
29
|
+
public/javascripts/lang/no.js
|
30
|
+
public/javascripts/lang/pt.js
|
31
|
+
public/javascripts/lang/ro.js
|
32
|
+
public/javascripts/lang/ru.js
|
33
|
+
public/javascripts/lang/sp.js
|
34
|
+
public/javascripts/lang/sv.js
|
35
|
+
public/javascripts/lang/ua.js
|
36
|
+
public/stylesheets/datepicker.css
|
37
|
+
spec/date_picker_tag_spec.rb
|
38
|
+
spec/date_picker_text_field_spec.rb
|
39
|
+
spec/datepicker_html_class_options_spec.rb
|
40
|
+
spec/spec.opts
|
41
|
+
spec/spec_helper.rb
|
42
|
+
spec/tag_matcher.rb
|
43
|
+
spec/unobtrusive_date_picker_spec.rb
|
44
|
+
tasks/datepicker_tasks.rake
|
45
|
+
uninstall.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
= Unobtrusive Date-Picker Widget Plugin
|
2
|
+
|
3
|
+
This is a helper for creating a date or date-time picker that uses the
|
4
|
+
Unobtrusive Date-Picker Widget(sic)
|
5
|
+
(http://www.frequency-decoder.com/2006/10/02/unobtrusive-date-picker-widgit-update)
|
6
|
+
to add a clickable calendar image that will bring up a calendar picker if
|
7
|
+
javascript is available. It replicates as much of the API of the Rails
|
8
|
+
`date_select`, and `datetime_select` form helpers.
|
9
|
+
|
10
|
+
It also uses the 12 Hour Time plugin
|
11
|
+
(http://code.google.com/p/rails-twelve-hour-time-plugin/) so that 12 Hour times
|
12
|
+
can be processed by Active Record.
|
13
|
+
|
14
|
+
You may want to consider compressing the javascript files with Dean Edward's
|
15
|
+
Packer (http://dean.edwards.name/packer/) or Douglas Crockford's JSMin
|
16
|
+
(http://www.crockford.com/javascript/jsmin.html) before deploying your
|
17
|
+
application.
|
18
|
+
|
19
|
+
== Install
|
20
|
+
|
21
|
+
`script/plugin install git://github.com/brianjlandau/unobtrusive_date_picker.git`
|
22
|
+
|
23
|
+
== Usage
|
24
|
+
|
25
|
+
To be able to use the date-picker methods below you need to include the
|
26
|
+
javascript library file and CSS stylesheet in the <head> of your layout
|
27
|
+
template. You can do this either by manually including the files via a
|
28
|
+
`javascript_include_tag` and a `stylesheet_link_tag` (the files are both named
|
29
|
+
"datepicker"), OR by using the included `unobtrusive_datepicker_includes` helper
|
30
|
+
method, which will do this for you.
|
31
|
+
|
32
|
+
There are 4 main methods:
|
33
|
+
- unobtrusive_date_picker
|
34
|
+
- unobtrusive_datetime_picker
|
35
|
+
- unobtrusive_date_picker_tags
|
36
|
+
- unobtrusive_datetime_picker_tags
|
37
|
+
- unobtrusive_date_text_picker
|
38
|
+
- unobtrusive_date_text_picker_tag
|
39
|
+
|
40
|
+
Options (* indicates same functionality as is in Rails Date helpers):
|
41
|
+
- *:order => the order the selects should be positioned in
|
42
|
+
- *:include_blank => include a blank option at the top of every select
|
43
|
+
- *:start_year => year that the year select should start on (defaults to 5
|
44
|
+
below either the year of the date value or current year)
|
45
|
+
- *:end_year => year that the year select should end on (defaults to 5 above
|
46
|
+
either the year of the date value or current year)
|
47
|
+
- *:minute_step => how many minutes apart each minute option should be
|
48
|
+
- example: (:minute_step => 5) would result in [0, 15, 30, 45] as options
|
49
|
+
- *:use_short_month => use short month names (Jan, Feb, etc.) instead of long
|
50
|
+
names (January) for option text
|
51
|
+
- *:use_month_numbers => use month numbers instead of names for option text
|
52
|
+
- *:add_month_numbers => add month numbers to names for option text ("1 - January")
|
53
|
+
- :highlight_days => which days of the week should be highlighted in the datepicker (by default Saturday and Sunday)
|
54
|
+
- Excepts either a string of number representing days of the week (0 = Monday, 1 = Tuesday ... 6 = Sunday)
|
55
|
+
- Or a singular symbol for one day of the week
|
56
|
+
- Or an array of symbols representing days of the week, i.e. [:Monday, :Sunday]
|
57
|
+
- :range_low => the low range of acceptable dates (not times) for this input
|
58
|
+
- managed by the Javascript, thus should be enforced with your own validations
|
59
|
+
- Excepts:
|
60
|
+
- One of the following symbols: :today, :tomorrow, :yesterday
|
61
|
+
- A string representation of a date
|
62
|
+
- A Date, DateTime, or Time object
|
63
|
+
- :range_high => the high range of acceptable dates (not times) for this input
|
64
|
+
- Excepts same options as :range_low; also managed by javascript
|
65
|
+
- :disable_days => days of the week that may not be selected
|
66
|
+
- Excepts the same format as :highlight_days
|
67
|
+
- Also managed by javascript
|
68
|
+
- :no_transparency => if set to true it disables the fade in/out
|
69
|
+
visual effect of the datepicker
|
70
|
+
|
71
|
+
The `unobtrusive_date_text_picker` and `unobtrusive_date_text_picker_tag` methods
|
72
|
+
don't except the ":order", ":include_blank", ":start_year", ":end_year", ":minute_step", ":use_short_month",
|
73
|
+
":use_month_numbers", and ":add_month_numbers" options.
|
74
|
+
It does use these options though:
|
75
|
+
- :format => the format the date should be in
|
76
|
+
- m-d-y
|
77
|
+
- d-m-y
|
78
|
+
- y-m-d
|
79
|
+
- :divider => the divider used between the dates
|
80
|
+
- "slash" or "/"
|
81
|
+
- "dash" or "-"
|
82
|
+
- "dot" or "."
|
83
|
+
- "space" or " "
|
84
|
+
|
85
|
+
|
86
|
+
==== RJS Method
|
87
|
+
|
88
|
+
There is an additional RJS method to re initialize the Date Pickers when an AJAX
|
89
|
+
response is supplied to the client:
|
90
|
+
|
91
|
+
- unobtrusive_date_picker_create
|
92
|
+
- This method can accept the DOM ID of a year select element to turn into
|
93
|
+
a date picker widget or if none is provided it will create all based on
|
94
|
+
the appropriate class name.
|
95
|
+
|
96
|
+
|
97
|
+
==== Rake task
|
98
|
+
|
99
|
+
There is also a rake task that can be executed by running `rake
|
100
|
+
datepicker:update` in your Rails apps root directory. This task will update your
|
101
|
+
datepicker javascripts, stylesheets, and images. This is useful if you are using
|
102
|
+
an old version of the plugin that had an older version of the Unobtrusive
|
103
|
+
Date-Picker Widget Javascript library, or in the future when new version are
|
104
|
+
release and I update the plugin with them.
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
=== Example:
|
109
|
+
<% form_for :article, :url => { :action => @form_action, :id => @article } do |f| %>
|
110
|
+
<fieldset>
|
111
|
+
...
|
112
|
+
<label>Date: <%= f.unobtrusive_datetime_picker :date %></label><br />
|
113
|
+
...
|
114
|
+
</fieldset>
|
115
|
+
<% end %>
|
116
|
+
|
117
|
+
=== Produces (Current date when output: 12/6/07):
|
118
|
+
<form action="/form/create" method="post">
|
119
|
+
<fieldset>
|
120
|
+
|
121
|
+
<label>Date:
|
122
|
+
<select id="article_date-dd" name="article[date(3i)]">
|
123
|
+
<option value="1">1</option>
|
124
|
+
...
|
125
|
+
<option value="31">31</option>
|
126
|
+
</select>
|
127
|
+
<select id="article_date-mm" name="article[date(2i)]">
|
128
|
+
<option value="1">January</option>
|
129
|
+
...
|
130
|
+
<option value="12" selected="selected">December</option>
|
131
|
+
</select>
|
132
|
+
<select id="article_date" name="article[date(1i)]" class="split-date">
|
133
|
+
<option value="2002">2002</option>
|
134
|
+
...
|
135
|
+
<option value="2012">2012</option>
|
136
|
+
</select>
|
137
|
+
|
138
|
+
<select id="article_date_4i" name="article[date(4i)][hour]">
|
139
|
+
<option value="1">1</option>
|
140
|
+
...
|
141
|
+
<option value="12">12</option>
|
142
|
+
</select>
|
143
|
+
:
|
144
|
+
<select id="article_date_5i" name="article[date(5i)][minute]">
|
145
|
+
<option value="00">00</option>
|
146
|
+
...
|
147
|
+
<option value="59">59</option>
|
148
|
+
</select>
|
149
|
+
<select id="article_date_6i" name="article[date(6i)][ampm]">
|
150
|
+
<option value="AMPM>AMPM</option>
|
151
|
+
<option value="AMPM>AMPM</option>
|
152
|
+
</select>
|
153
|
+
</label><br />
|
154
|
+
|
155
|
+
</fieldset>
|
156
|
+
</form>
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
== LICENSE
|
161
|
+
|
162
|
+
See MIT-LICENSE file for copyright and licensing information for this plugin.
|
163
|
+
|
164
|
+
Unobtrusive Date-Picker Widget is provided under the Creative Commons Attribution-ShareAlike 2.5 license (http://creativecommons.org/licenses/by-sa/2.5/) by frequency-decoder.com
|
165
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
desc 'Generate documentation for the unobtrusive_date_picker plugin.'
|
7
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
8
|
+
rdoc.rdoc_dir = 'rdoc'
|
9
|
+
rdoc.title = 'Unobtrusive Date-Picker'
|
10
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
11
|
+
rdoc.rdoc_files.add ['lib/**/*.rb', 'README.rdoc']
|
12
|
+
rdoc.options << '--main' << 'README.rdoc'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run all specs"
|
16
|
+
Spec::Rake::SpecTask.new do |t|
|
17
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'echoe'
|
21
|
+
|
22
|
+
Echoe.new('unobtrusive_date_picker', '0.1.0') do |p|
|
23
|
+
p.description = "Helper for creating a date or date-time picker that uses the Unobtrusive Date-Picker Widge"
|
24
|
+
p.url = "http://github.com/brianjlandau/unobtrusive_date_picker"
|
25
|
+
p.author = "Brian landau"
|
26
|
+
p.email = ""
|
27
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
28
|
+
p.development_dependencies = []
|
29
|
+
end
|
data/about.yml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
name: Unobtrusive Date-Picker Widget
|
2
|
+
author: Brian Landau
|
3
|
+
version: 2.0
|
4
|
+
description: Helper to create a set of Date/Time selects that use the Unobtrusive Date Picker Widget.
|
5
|
+
url: http://github.com/brianjlandau/unobtrusive_date_picker/
|
6
|
+
install: git@github.com:brianjlandau/unobtrusive_date_picker.git
|
7
|
+
license: MIT
|
data/init.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require '12_hour_time'
|
2
|
+
require 'unobtrusive_date_picker'
|
3
|
+
|
4
|
+
# Include all the necessary functions in to the appropriate point in the Rails framework
|
5
|
+
ActionView::Base.send :include, UnobtrusiveDatePicker::UnobtrusiveDatePickerHelper
|
6
|
+
ActionView::Helpers::DateHelper.send :include, UnobtrusiveDatePicker::UnobtrusiveDatePickerHelper
|
7
|
+
ActionView::Base.send :include, UnobtrusiveDatePicker::AssetTagHelper
|
8
|
+
ActionView::Helpers::AssetTagHelper.send :include, UnobtrusiveDatePicker::AssetTagHelper
|
data/install.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# Install all the needed support files (CSS and JavaScript)
|
4
|
+
|
5
|
+
js_dir = File.dirname(__FILE__) + '/../../../public/javascripts/'
|
6
|
+
datepicker_js = js_dir + 'datepicker.js'
|
7
|
+
lang_dir = js_dir + 'lang'
|
8
|
+
datepicker_css = File.dirname(__FILE__) + '/../../../public/stylesheets/datepicker.css'
|
9
|
+
images_dir = File.dirname(__FILE__) + '/../../../public/images/datepicker'
|
10
|
+
|
11
|
+
FileUtils.cp File.dirname(__FILE__) + '/public/javascripts/datepicker.js', datepicker_js unless File.exists?(datepicker_js)
|
12
|
+
FileUtils.cp_r File.dirname(__FILE__) + '/public/javascripts/lang/', lang_dir unless File.exists?(lang_dir)
|
13
|
+
FileUtils.cp File.dirname(__FILE__) + '/public/stylesheets/datepicker.css', datepicker_css unless File.exists?(datepicker_css)
|
14
|
+
FileUtils.cp_r File.dirname(__FILE__) + '/public/images/', images_dir unless File.exists?(images_dir)
|
data/lib/12_hour_time.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#
|
2
|
+
# == Rails Twelve Hour Time Plugin
|
3
|
+
#
|
4
|
+
# http://code.google.com/p/rails-twelve-hour-time-plugin/
|
5
|
+
#
|
6
|
+
# ==== Authors
|
7
|
+
# * Nick Muerdter (original code)
|
8
|
+
# * Maurice Aubrey
|
9
|
+
#
|
10
|
+
# ==== Used for
|
11
|
+
# Allows UnobtrusiveDatePicker::UnobtrusiveDatePickerHelper to use a AM/PM select of it's own,
|
12
|
+
# and still be processed correctly by Active Record.
|
13
|
+
#
|
14
|
+
|
15
|
+
# :enddoc:
|
16
|
+
if defined? ActiveRecord
|
17
|
+
class ActiveRecord::Base # :nodoc: all
|
18
|
+
def instantiate_time_object_with_ampm(name, values)
|
19
|
+
if values.last < 0
|
20
|
+
ampm = values.pop
|
21
|
+
if ampm == ActionView::Helpers::DateTimeSelector::AM and values[3] == 12
|
22
|
+
values[3] = 0
|
23
|
+
elsif ampm == ActionView::Helpers::DateTimeSelector::PM and values[3] != 12
|
24
|
+
values[3] += 12
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
instantiate_time_object_without_ampm(name, values)
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method_chain :instantiate_time_object, :ampm
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
ActionView::Helpers::DateTimeSelector.send(:remove_const, :POSITION)
|
36
|
+
ActionView::Helpers::DateTimeSelector.const_set(:POSITION, {
|
37
|
+
:year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5,
|
38
|
+
:second => 6, :ampm => 7
|
39
|
+
})
|
40
|
+
|
41
|
+
# Included manully in UnobtrusiveDatePicker
|
42
|
+
# module ActionView::Helpers
|
43
|
+
# class DateTimeSelector
|
44
|
+
# POSITION = {
|
45
|
+
# :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5,
|
46
|
+
# :second => 6, :ampm => 7
|
47
|
+
# }
|
48
|
+
# # XXX would like to do this, but it's frozen
|
49
|
+
# # POSITION[:ampm] = 7
|
50
|
+
#
|
51
|
+
# # We give them negative values so can differentiate between normal
|
52
|
+
# # date/time values. The way the multi param stuff works, from what I
|
53
|
+
# # can see, results in a variable number of fields (if you tell it to
|
54
|
+
# # include seconds, for example). So we expect the AM/PM field, if
|
55
|
+
# # present, to be last and have a negative value.
|
56
|
+
# AM = -1
|
57
|
+
# PM = -2
|
58
|
+
#
|
59
|
+
# def select_hour_with_ampm
|
60
|
+
# unless @options[:twelve_hour]
|
61
|
+
# return select_hour_without_ampm
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# if @options[:use_hidden] || @options[:discard_hour]
|
65
|
+
# build_hidden(:hour, hour12)
|
66
|
+
# else
|
67
|
+
# build_options_and_select(:hour, hour12, :start => 1, :end => 12)
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# alias_method_chain :select_hour, :ampm
|
72
|
+
#
|
73
|
+
# def select_ampm
|
74
|
+
# selected = hour < 12 ? AM : PM
|
75
|
+
#
|
76
|
+
# # XXX i18n?
|
77
|
+
# label = { AM => 'AM', PM => 'PM' }
|
78
|
+
# ampm_options = []
|
79
|
+
# [AM, PM].each do |meridiem|
|
80
|
+
# option = { :value => meridiem }
|
81
|
+
# option[:selected] = "selected" if selected == meridiem
|
82
|
+
# ampm_options << content_tag(:option, label[meridiem], option) + "\n"
|
83
|
+
# end
|
84
|
+
# build_select(:ampm, ampm_options.join)
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# private
|
88
|
+
#
|
89
|
+
# def build_selects_from_types_with_ampm(order)
|
90
|
+
# order += [:ampm] if @options[:twelve_hour] and !order.include?(:ampm)
|
91
|
+
# build_selects_from_types_without_ampm(order)
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# alias_method_chain :build_selects_from_types, :ampm
|
95
|
+
#
|
96
|
+
# def hour12
|
97
|
+
# h12 = hour % 12
|
98
|
+
# h12 = 12 if h12 == 0
|
99
|
+
# return h12
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
# end
|
@@ -0,0 +1,407 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '12_hour_time')
|
2
|
+
|
3
|
+
module UnobtrusiveDatePicker
|
4
|
+
|
5
|
+
DATEPICKER_DEFAULT_NAME_ID_SUFFIXES = { :year => {:id => '', :name => 'year'},
|
6
|
+
:month => {:id => 'mm', :name => 'month'},
|
7
|
+
:day => {:id => 'dd', :name => 'day'} }
|
8
|
+
|
9
|
+
DATEPICKER_DAYS_OF_WEEK = { :Monday => '0',
|
10
|
+
:Tuesday => '1',
|
11
|
+
:Wednesday => '2',
|
12
|
+
:Thursday => '3',
|
13
|
+
:Friday => '4',
|
14
|
+
:Saturday => '5',
|
15
|
+
:Sunday => '6'}
|
16
|
+
|
17
|
+
DATEPICKER_DIVIDERS = { 'slash' => '/',
|
18
|
+
'dash' => '-',
|
19
|
+
'dot' => '.',
|
20
|
+
'space' => ' ' }
|
21
|
+
|
22
|
+
RANGE_DATE_FORMAT = '%Y-%m-%d'
|
23
|
+
|
24
|
+
# == Unobtrusive Date-Picker Helper
|
25
|
+
#
|
26
|
+
# This Module helps to create date and date-time fields that use the
|
27
|
+
# Unobtrusive Date-Picker Javascript Widget.
|
28
|
+
#
|
29
|
+
# They also use the 12-hour AM/PM time format.
|
30
|
+
#
|
31
|
+
module UnobtrusiveDatePickerHelper
|
32
|
+
|
33
|
+
##
|
34
|
+
# Creates the date picker with the calendar widget.
|
35
|
+
#
|
36
|
+
def unobtrusive_date_picker(object_name, method, options = {}, html_options = {})
|
37
|
+
ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_datepicker_date_select_tag(options, html_options)
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Creates the date-time picker with the calendar widget, and AM/PM select.
|
42
|
+
#
|
43
|
+
def unobtrusive_datetime_picker(object_name, method, options = {}, html_options = {})
|
44
|
+
ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_datepicker_datetime_select_tag(options, html_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Creates the date picker with the calendar widget.
|
49
|
+
#
|
50
|
+
def unobtrusive_date_text_picker(object_name, method, options = {}, html_options = {})
|
51
|
+
ActionView::Helpers::InstanceTag.new(object_name, method, self, options.delete(:object)).to_datepicker_text_tag(options, html_options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def unobtrusive_datetime_picker_tags(datetime = Time.current, options = {}, html_options = {})
|
55
|
+
datetime ||= Time.current
|
56
|
+
DateTimePickerSelector.new(datetime, options.merge(:twelve_hour => true), html_options).select_datetime
|
57
|
+
end
|
58
|
+
|
59
|
+
def unobtrusive_date_picker_tags(date = Date.current, options = {}, html_options = {})
|
60
|
+
date ||= Date.current
|
61
|
+
DateTimePickerSelector.new(date, options, html_options).select_date
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Creates the text field based date picker with the calendar widget without a model object.
|
66
|
+
#
|
67
|
+
def unobtrusive_date_text_picker_tag(name, date = Date.current, options = {}, html_options = {})
|
68
|
+
date ||= Date.current
|
69
|
+
options = merge_defaults_for_text_picker(options)
|
70
|
+
DateTimePickerSelector.new(date, options, html_options).text_date_picker(name)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def merge_defaults_for_text_picker(options)
|
75
|
+
defaults = {:format => 'm-d-y', :divider => 'slash'}
|
76
|
+
options = defaults.merge(options)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
module AssetTagHelper
|
82
|
+
##
|
83
|
+
# This will add the necessary <link> and <script> tags to include the necessary stylesheet and
|
84
|
+
# javascripts.
|
85
|
+
#
|
86
|
+
def unobtrusive_datepicker_includes(options = {})
|
87
|
+
tags = []
|
88
|
+
tags << javascript_include_tag('datepicker', options)
|
89
|
+
tags << stylesheet_link_tag('datepicker', options)
|
90
|
+
tags * "\n"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
module OptionParser
|
95
|
+
protected
|
96
|
+
def parse_divider_option(option)
|
97
|
+
if DATEPICKER_DIVIDERS.keys.include?(option)
|
98
|
+
option
|
99
|
+
else
|
100
|
+
DATEPICKER_DIVIDERS.find {|name, value| option == value}.first
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def format_date_value_for_text_field(value, format, divider_option)
|
105
|
+
divider = DATEPICKER_DIVIDERS[parse_divider_option(divider_option)]
|
106
|
+
format_string = format.downcase.gsub(/(m|d)/, '%\1').gsub(/y/, '%Y').gsub('-', divider)
|
107
|
+
value.nil? ? '' : value.strftime(format_string)
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_html_classes_for_datepicker(options, html_options_class, extra_class = nil)
|
111
|
+
html_classes = make_date_picker_class_options(options)
|
112
|
+
html_classes << extra_class if extra_class
|
113
|
+
html_options_class.blank? ?
|
114
|
+
html_classes.join(' ') : "#{html_options_class} #{html_classes.join(' ')}"
|
115
|
+
end
|
116
|
+
|
117
|
+
def make_date_picker_class_options(options)
|
118
|
+
html_classes = []
|
119
|
+
|
120
|
+
if options[:highlight_days]
|
121
|
+
highlight_days = parse_days_of_week(options[:highlight_days])
|
122
|
+
if !highlight_days.blank?
|
123
|
+
html_classes << "highlight-days-#{highlight_days}"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if options[:range_low]
|
128
|
+
range_low = parse_range_option(options[:range_low], 'low')
|
129
|
+
if !range_low.blank?
|
130
|
+
html_classes << range_low
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if options[:range_high]
|
135
|
+
range_high = parse_range_option(options[:range_high], 'high')
|
136
|
+
if !range_high.blank?
|
137
|
+
html_classes << range_high
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
if options[:disable_days]
|
142
|
+
disable_days = parse_days_of_week(options[:disable_days])
|
143
|
+
if !disable_days.blank?
|
144
|
+
html_classes << "disable-days-#{disable_days}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
if options[:no_transparency]
|
149
|
+
html_classes << 'no-transparency'
|
150
|
+
end
|
151
|
+
|
152
|
+
if options[:format] && %W(d-m-y m-d-y y-m-d).include?(options[:format].downcase)
|
153
|
+
html_classes << "format-#{options[:format].downcase}"
|
154
|
+
end
|
155
|
+
|
156
|
+
if options[:divider]
|
157
|
+
html_classes << "divider-#{parse_divider_option(options[:divider])}"
|
158
|
+
end
|
159
|
+
|
160
|
+
html_classes
|
161
|
+
end
|
162
|
+
|
163
|
+
def parse_days_of_week(option)
|
164
|
+
if option.is_a? String
|
165
|
+
option
|
166
|
+
elsif option.is_a? Symbol
|
167
|
+
DATEPICKER_DAYS_OF_WEEK[option]
|
168
|
+
elsif option.is_a? Array
|
169
|
+
days = ''
|
170
|
+
option.each do |day|
|
171
|
+
days << DATEPICKER_DAYS_OF_WEEK[day]
|
172
|
+
end
|
173
|
+
days
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def parse_range_option(option, direction)
|
178
|
+
if option.is_a? Symbol
|
179
|
+
case option
|
180
|
+
when :today
|
181
|
+
range_class = 'today'
|
182
|
+
when :tomorrow
|
183
|
+
range_class = Date.tomorrow.strftime(RANGE_DATE_FORMAT)
|
184
|
+
when :yesterday
|
185
|
+
range_class = Date.yesterday.strftime(RANGE_DATE_FORMAT)
|
186
|
+
end
|
187
|
+
elsif option.is_a? String
|
188
|
+
if !option.blank?
|
189
|
+
range_class = Date.parse(option).strftime(RANGE_DATE_FORMAT)
|
190
|
+
else
|
191
|
+
range_class = nil
|
192
|
+
end
|
193
|
+
elsif (option.is_a?(Date) || option.is_a?(DateTime) || option.is_a?(Time))
|
194
|
+
range_class = option.strftime(RANGE_DATE_FORMAT)
|
195
|
+
else
|
196
|
+
range_class = nil
|
197
|
+
end
|
198
|
+
|
199
|
+
if !range_class.blank?
|
200
|
+
range_class = 'range-' + direction + '-' + range_class
|
201
|
+
else
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class DateTimePickerSelector < ActionView::Helpers::DateTimeSelector
|
208
|
+
include ActionView::Helpers::FormTagHelper
|
209
|
+
include OptionParser
|
210
|
+
|
211
|
+
POSITION = {
|
212
|
+
:year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5,
|
213
|
+
:second => 6, :ampm => 7
|
214
|
+
}
|
215
|
+
# XXX would like to do this, but it's frozen
|
216
|
+
# POSITION[:ampm] = 7
|
217
|
+
|
218
|
+
# We give them negative values so can differentiate between normal
|
219
|
+
# date/time values. The way the multi param stuff works, from what I
|
220
|
+
# can see, results in a variable number of fields (if you tell it to
|
221
|
+
# include seconds, for example). So we expect the AM/PM field, if
|
222
|
+
# present, to be last and have a negative value.
|
223
|
+
AM = -1
|
224
|
+
PM = -2
|
225
|
+
|
226
|
+
def text_date_picker(name)
|
227
|
+
value = format_date_value_for_text_field(@datetime, @options[:format], @options[:divider])
|
228
|
+
@html_options[:class] = get_html_classes_for_datepicker(@options, @html_options[:class])
|
229
|
+
text_field_tag(name, value, @html_options)
|
230
|
+
end
|
231
|
+
|
232
|
+
def select_hour_with_ampm
|
233
|
+
unless @options[:twelve_hour]
|
234
|
+
return select_hour_without_ampm
|
235
|
+
end
|
236
|
+
|
237
|
+
if @options[:use_hidden] || @options[:discard_hour]
|
238
|
+
build_hidden(:hour, hour12)
|
239
|
+
else
|
240
|
+
build_options_and_select(:hour, hour12, :start => 1, :end => 12)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
alias_method_chain :select_hour, :ampm
|
245
|
+
|
246
|
+
def select_ampm
|
247
|
+
selected = hour < 12 ? AM : PM
|
248
|
+
|
249
|
+
# XXX i18n?
|
250
|
+
label = { AM => 'AM', PM => 'PM' }
|
251
|
+
ampm_options = []
|
252
|
+
[AM, PM].each do |meridiem|
|
253
|
+
option = { :value => meridiem }
|
254
|
+
option[:selected] = "selected" if selected == meridiem
|
255
|
+
ampm_options << content_tag(:option, label[meridiem], option) + "\n"
|
256
|
+
end
|
257
|
+
build_select(:ampm, ampm_options.join)
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
def build_selects_from_types_with_ampm(order)
|
262
|
+
order += [:ampm] if @options[:twelve_hour] and !order.include?(:ampm)
|
263
|
+
build_selects_from_types_without_ampm(order)
|
264
|
+
end
|
265
|
+
|
266
|
+
alias_method_chain :build_selects_from_types, :ampm
|
267
|
+
|
268
|
+
def hour12
|
269
|
+
h12 = hour % 12
|
270
|
+
h12 = 12 if h12 == 0
|
271
|
+
return h12
|
272
|
+
end
|
273
|
+
|
274
|
+
def build_select(type, select_options_as_html)
|
275
|
+
select_options = @html_options.merge(
|
276
|
+
:id => input_id_from_type(type, @html_options[:id]),
|
277
|
+
:name => input_name_from_type(type)
|
278
|
+
)
|
279
|
+
select_options.merge!(:disabled => 'disabled') if @options[:disabled]
|
280
|
+
|
281
|
+
if type.to_sym == :year
|
282
|
+
select_options[:class] = get_html_classes_for_datepicker(@options, select_options[:class], 'split-date')
|
283
|
+
end
|
284
|
+
|
285
|
+
select_html = "\n"
|
286
|
+
select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank]
|
287
|
+
select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
|
288
|
+
select_html << select_options_as_html.to_s
|
289
|
+
|
290
|
+
content_tag(:select, select_html, select_options) + "\n"
|
291
|
+
end
|
292
|
+
|
293
|
+
def build_hidden(type, value)
|
294
|
+
hidden_html_options = {
|
295
|
+
:type => "hidden",
|
296
|
+
:id => input_id_from_type(type, @html_options[:id]),
|
297
|
+
:name => input_name_from_type(type),
|
298
|
+
:value => value
|
299
|
+
}
|
300
|
+
|
301
|
+
if type.to_sym == :year
|
302
|
+
hidden_html_options[:class] = get_html_classes_for_datepicker(@options, hidden_html_options[:class], 'split-date')
|
303
|
+
end
|
304
|
+
|
305
|
+
tag(:input, hidden_html_options) + "\n"
|
306
|
+
end
|
307
|
+
|
308
|
+
def input_id_from_type(type, html_options_id = nil)
|
309
|
+
if html_options_id.blank?
|
310
|
+
prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
|
311
|
+
prefix += "_#{@options[:index]}" if @options.has_key?(:index)
|
312
|
+
prefix += "_#{@options[:field_name]}" if @options.has_key?(:field_name)
|
313
|
+
else
|
314
|
+
prefix = html_options_id
|
315
|
+
end
|
316
|
+
case type.to_sym
|
317
|
+
when :year
|
318
|
+
prefix
|
319
|
+
when :month
|
320
|
+
prefix + '-mm'
|
321
|
+
when :day
|
322
|
+
prefix + '-dd'
|
323
|
+
else
|
324
|
+
super(type)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
end
|
331
|
+
# /UnobtrusiveDatePicker
|
332
|
+
|
333
|
+
module ActionView # :nodoc: all
|
334
|
+
module Helpers
|
335
|
+
class InstanceTag
|
336
|
+
include UnobtrusiveDatePicker::UnobtrusiveDatePickerHelper
|
337
|
+
include UnobtrusiveDatePicker::OptionParser
|
338
|
+
|
339
|
+
def to_datepicker_date_select_tag(options = {}, html_options = {})
|
340
|
+
datepicker_selector(options, html_options).select_date
|
341
|
+
end
|
342
|
+
|
343
|
+
def to_datepicker_datetime_select_tag(options = {}, html_options = {})
|
344
|
+
datepicker_selector(options.merge(:twelve_hour => true), html_options).select_datetime
|
345
|
+
end
|
346
|
+
|
347
|
+
def to_datepicker_text_tag(options = {}, html_options = {})
|
348
|
+
options = merge_defaults_for_text_picker(options)
|
349
|
+
html_options[:class] = get_html_classes_for_datepicker(options, html_options[:class])
|
350
|
+
html_options[:value] = format_date_value_for_text_field(value(object), options[:format], options[:divider])
|
351
|
+
to_input_field_tag('text', html_options)
|
352
|
+
end
|
353
|
+
|
354
|
+
private
|
355
|
+
def datepicker_selector(options, html_options)
|
356
|
+
datetime = value(object) || default_datetime(options)
|
357
|
+
|
358
|
+
options = options.dup
|
359
|
+
options[:field_name] = @method_name
|
360
|
+
options[:include_position] = true
|
361
|
+
options[:prefix] ||= @object_name
|
362
|
+
options[:index] = @auto_index if @auto_index && !options.has_key?(:index)
|
363
|
+
options[:datetime_separator] ||= ' — '
|
364
|
+
options[:time_separator] ||= ' : '
|
365
|
+
|
366
|
+
UnobtrusiveDatePicker::DateTimePickerSelector.new(datetime, options.merge(:tag => true), html_options)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
module ActionView::Helpers::PrototypeHelper
|
373
|
+
class JavaScriptGenerator
|
374
|
+
module GeneratorMethods
|
375
|
+
def unobtrusive_date_picker_create(id = nil)
|
376
|
+
if id
|
377
|
+
call "datePickerController.create", "$(#{id})"
|
378
|
+
else
|
379
|
+
record "datePickerController.create"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
def unobtrusive_date_picker_cleanup(id = nil)
|
384
|
+
record "datePickerController.cleanUp"
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
|
391
|
+
module ActionView # :nodoc: all
|
392
|
+
module Helpers
|
393
|
+
class FormBuilder
|
394
|
+
def unobtrusive_date_picker(method, options = {}, html_options = {})
|
395
|
+
@template.unobtrusive_date_picker(@object_name, method, objectify_options(options), html_options)
|
396
|
+
end
|
397
|
+
|
398
|
+
def unobtrusive_date_text_picker(method, options = {}, html_options = {})
|
399
|
+
@template.unobtrusive_date_text_picker(@object_name, method, objectify_options(options), html_options)
|
400
|
+
end
|
401
|
+
|
402
|
+
def unobtrusive_datetime_picker(method, options = {}, html_options = {})
|
403
|
+
@template.unobtrusive_datetime_picker(@object_name, method, objectify_options(options), html_options)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|