formtastic 2.1.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +1 -0
- data/.github/workflows/test.yml +61 -0
- data/.gitignore +4 -2
- data/CHANGELOG.md +52 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +105 -0
- data/MIT-LICENSE +1 -1
- data/{README.textile → README.md} +204 -219
- data/RELEASE_PROCESS +3 -1
- data/Rakefile +27 -29
- data/app/assets/stylesheets/formtastic.css +3 -2
- data/bin/appraisal +8 -0
- data/formtastic.gemspec +11 -14
- data/gemfiles/rails_5.2/Gemfile +5 -0
- data/gemfiles/rails_6.0/Gemfile +5 -0
- data/gemfiles/rails_6.1/Gemfile +5 -0
- data/gemfiles/rails_edge/Gemfile +13 -0
- data/lib/formtastic/action_class_finder.rb +18 -0
- data/lib/formtastic/actions/button_action.rb +55 -60
- data/lib/formtastic/actions/input_action.rb +59 -57
- data/lib/formtastic/actions/link_action.rb +68 -67
- data/lib/formtastic/actions.rb +6 -3
- data/lib/formtastic/deprecation.rb +5 -0
- data/lib/formtastic/engine.rb +3 -1
- data/lib/formtastic/form_builder.rb +35 -16
- data/lib/formtastic/helpers/action_helper.rb +34 -28
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/errors_helper.rb +2 -2
- data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
- data/lib/formtastic/helpers/form_helper.rb +19 -16
- data/lib/formtastic/helpers/input_helper.rb +69 -97
- data/lib/formtastic/helpers/inputs_helper.rb +35 -25
- data/lib/formtastic/helpers/reflection.rb +4 -4
- data/lib/formtastic/helpers.rb +1 -2
- data/lib/formtastic/html_attributes.rb +12 -1
- data/lib/formtastic/i18n.rb +1 -1
- data/lib/formtastic/input_class_finder.rb +18 -0
- data/lib/formtastic/inputs/base/choices.rb +2 -2
- data/lib/formtastic/inputs/base/collections.rb +46 -14
- data/lib/formtastic/inputs/base/database.rb +7 -2
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
- data/lib/formtastic/inputs/base/errors.rb +7 -7
- data/lib/formtastic/inputs/base/hints.rb +2 -2
- data/lib/formtastic/inputs/base/html.rb +10 -9
- data/lib/formtastic/inputs/base/labelling.rb +5 -8
- data/lib/formtastic/inputs/base/naming.rb +4 -4
- data/lib/formtastic/inputs/base/numeric.rb +1 -1
- data/lib/formtastic/inputs/base/options.rb +3 -4
- data/lib/formtastic/inputs/base/stringish.rb +10 -2
- data/lib/formtastic/inputs/base/timeish.rb +34 -22
- data/lib/formtastic/inputs/base/validations.rb +41 -13
- data/lib/formtastic/inputs/base/wrapping.rb +29 -26
- data/lib/formtastic/inputs/base.rb +22 -15
- data/lib/formtastic/inputs/boolean_input.rb +26 -12
- data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
- data/lib/formtastic/inputs/color_input.rb +41 -0
- data/lib/formtastic/inputs/country_input.rb +24 -5
- data/lib/formtastic/inputs/datalist_input.rb +41 -0
- data/lib/formtastic/inputs/date_picker_input.rb +93 -0
- data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
- data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
- data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
- data/lib/formtastic/inputs/file_input.rb +2 -2
- data/lib/formtastic/inputs/hidden_input.rb +2 -6
- data/lib/formtastic/inputs/radio_input.rb +28 -22
- data/lib/formtastic/inputs/select_input.rb +36 -39
- data/lib/formtastic/inputs/time_picker_input.rb +99 -0
- data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
- data/lib/formtastic/inputs/time_zone_input.rb +16 -6
- data/lib/formtastic/inputs.rb +32 -21
- data/lib/formtastic/localized_string.rb +1 -1
- data/lib/formtastic/localizer.rb +24 -24
- data/lib/formtastic/namespaced_class_finder.rb +99 -0
- data/lib/formtastic/version.rb +1 -1
- data/lib/formtastic.rb +20 -10
- data/lib/generators/formtastic/form/form_generator.rb +10 -4
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/formtastic/install/install_generator.rb +5 -19
- data/lib/generators/templates/_form.html.slim +2 -2
- data/lib/generators/templates/formtastic.rb +46 -25
- data/lib/generators/templates/input.rb +19 -0
- data/sample/basic_inputs.html +23 -3
- data/script/integration-template.rb +74 -0
- data/script/integration.sh +19 -0
- data/spec/action_class_finder_spec.rb +12 -0
- data/spec/actions/button_action_spec.rb +8 -8
- data/spec/actions/generic_action_spec.rb +92 -56
- data/spec/actions/input_action_spec.rb +7 -7
- data/spec/actions/link_action_spec.rb +10 -10
- data/spec/builder/custom_builder_spec.rb +36 -20
- data/spec/builder/error_proc_spec.rb +4 -4
- data/spec/builder/semantic_fields_for_spec.rb +28 -29
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
- data/spec/helpers/action_helper_spec.rb +75 -103
- data/spec/helpers/actions_helper_spec.rb +17 -17
- data/spec/helpers/form_helper_spec.rb +84 -33
- data/spec/helpers/input_helper_spec.rb +333 -285
- data/spec/helpers/inputs_helper_spec.rb +167 -121
- data/spec/helpers/reflection_helper_spec.rb +3 -3
- data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
- data/spec/i18n_spec.rb +26 -26
- data/spec/input_class_finder_spec.rb +10 -0
- data/spec/inputs/base/collections_spec.rb +76 -0
- data/spec/inputs/base/validations_spec.rb +480 -0
- data/spec/inputs/boolean_input_spec.rb +100 -65
- data/spec/inputs/check_boxes_input_spec.rb +200 -101
- data/spec/inputs/color_input_spec.rb +85 -0
- data/spec/inputs/country_input_spec.rb +20 -20
- data/spec/inputs/custom_input_spec.rb +3 -4
- data/spec/inputs/datalist_input_spec.rb +61 -0
- data/spec/inputs/date_picker_input_spec.rb +449 -0
- data/spec/inputs/date_select_input_spec.rb +249 -0
- data/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/spec/inputs/datetime_select_input_spec.rb +209 -0
- data/spec/inputs/email_input_spec.rb +5 -5
- data/spec/inputs/file_input_spec.rb +6 -6
- data/spec/inputs/hidden_input_spec.rb +22 -35
- data/spec/inputs/include_blank_spec.rb +11 -11
- data/spec/inputs/label_spec.rb +62 -25
- data/spec/inputs/number_input_spec.rb +112 -112
- data/spec/inputs/password_input_spec.rb +5 -5
- data/spec/inputs/phone_input_spec.rb +5 -5
- data/spec/inputs/placeholder_spec.rb +6 -6
- data/spec/inputs/radio_input_spec.rb +99 -55
- data/spec/inputs/range_input_spec.rb +66 -66
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/search_input_spec.rb +5 -5
- data/spec/inputs/select_input_spec.rb +170 -170
- data/spec/inputs/string_input_spec.rb +68 -16
- data/spec/inputs/text_input_spec.rb +16 -16
- data/spec/inputs/time_picker_input_spec.rb +455 -0
- data/spec/inputs/time_select_input_spec.rb +261 -0
- data/spec/inputs/time_zone_input_spec.rb +54 -28
- data/spec/inputs/url_input_spec.rb +5 -5
- data/spec/inputs/with_options_spec.rb +7 -7
- data/spec/localizer_spec.rb +39 -17
- data/spec/namespaced_class_finder_spec.rb +79 -0
- data/spec/schema.rb +21 -0
- data/spec/spec_helper.rb +254 -221
- data/spec/support/custom_macros.rb +128 -95
- data/spec/support/shared_examples.rb +12 -0
- data/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/spec/support/test_environment.rb +26 -10
- metadata +177 -238
- data/.travis.yml +0 -8
- data/Appraisals +0 -11
- data/CHANGELOG +0 -371
- data/gemfiles/rails-3.0.gemfile +0 -7
- data/gemfiles/rails-3.1.gemfile +0 -7
- data/gemfiles/rails-3.2.gemfile +0 -7
- data/lib/formtastic/helpers/buttons_helper.rb +0 -310
- data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
- data/lib/formtastic/util.rb +0 -25
- data/lib/tasks/verify_rcov.rb +0 -44
- data/spec/helpers/buttons_helper_spec.rb +0 -166
- data/spec/helpers/commit_button_helper_spec.rb +0 -530
- data/spec/inputs/date_input_spec.rb +0 -227
- data/spec/inputs/datetime_input_spec.rb +0 -185
- data/spec/inputs/time_input_spec.rb +0 -267
- data/spec/support/deferred_garbage_collection.rb +0 -21
@@ -4,13 +4,15 @@ module Formtastic
|
|
4
4
|
# Rails doesn't come with a `country_select` helper by default any more, so you'll need to do
|
5
5
|
# one of the following:
|
6
6
|
#
|
7
|
-
# * install the [
|
8
|
-
# * install the no longer maintained [official Rails plugin](http://github.com/rails/iso-3166-country-select)
|
7
|
+
# * install the [country_select](https://github.com/stefanpenner/country_select) gem
|
9
8
|
# * install any other country_select plugin that behaves in a similar way
|
10
9
|
# * roll your own `country_select` helper with the same args and options as the Rails one
|
11
10
|
#
|
11
|
+
# Formtastic supports both 1.x and 2.x of stefanpenner/country_select, but if you're upgrading
|
12
|
+
# from 1.x, they behave quite differently, so please see their [upgrade instructions](https://github.com/stefanpenner/country_select/blob/master/UPGRADING.md).
|
13
|
+
#
|
12
14
|
# By default, Formtastic includes a handful of English-speaking countries as "priority
|
13
|
-
#
|
15
|
+
# countries", which can be set in the `priority_countries` configuration array in the
|
14
16
|
# formtastic.rb initializer to suit your market and user base (see README for more info on
|
15
17
|
# configuration). Additionally, it is possible to set the :priority_countries on a per-input
|
16
18
|
# basis through the `:priority_countries` option. These priority countries will be passed down
|
@@ -31,7 +33,7 @@ module Formtastic
|
|
31
33
|
# # ...
|
32
34
|
# </li>
|
33
35
|
#
|
34
|
-
# @example `:priority_countries` set on a specific input
|
36
|
+
# @example `:priority_countries` set on a specific input (country_select 1.x)
|
35
37
|
#
|
36
38
|
# <%= semantic_form_for @user do |f| %>
|
37
39
|
# <%= f.inputs do %>
|
@@ -46,12 +48,29 @@ module Formtastic
|
|
46
48
|
# # ...
|
47
49
|
# </li>
|
48
50
|
#
|
51
|
+
# @example `:priority_countries` set on a specific input (country_select 2.x)
|
52
|
+
#
|
53
|
+
# <%= semantic_form_for @user do |f| %>
|
54
|
+
# <%= f.inputs do %>
|
55
|
+
# <%= f.input :nationality, :as => :country, :priority_countries => ["AU", "NZ"] %>
|
56
|
+
# <% end %>
|
57
|
+
# <% end %>
|
58
|
+
#
|
59
|
+
# <li class='country'>
|
60
|
+
# <label for="user_nationality">Country</label>
|
61
|
+
# <select id="user_nationality" name="user[nationality]">
|
62
|
+
# <option value="...">...</option>
|
63
|
+
# # ...
|
64
|
+
# </li>
|
65
|
+
#
|
49
66
|
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
50
67
|
class CountryInput
|
51
68
|
include Base
|
52
69
|
|
70
|
+
CountrySelectPluginMissing = Class.new(StandardError)
|
71
|
+
|
53
72
|
def to_html
|
54
|
-
raise "To use the :country input, please install a country_select plugin, like this one: https://github.com/
|
73
|
+
raise CountrySelectPluginMissing, "To use the :country input, please install a country_select plugin, like this one: https://github.com/stefanpenner/country_select" unless builder.respond_to?(:country_select)
|
55
74
|
input_wrapping do
|
56
75
|
label_html <<
|
57
76
|
builder.country_select(method, priority_countries, input_options, input_html_options)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module Inputs
|
3
|
+
# Outputs a label and a text field, along with a datalist tag
|
4
|
+
# datalist tag provides a list of options which drives a simple autocomplete
|
5
|
+
# on the text field. This is a HTML5 feature, more info can be found at
|
6
|
+
# {https://developer.mozilla.org/en/docs/Web/HTML/Element/datalist <datalist> at MDN}
|
7
|
+
# This input accepts a :collection option which takes data in all the usual formats accepted by
|
8
|
+
# {http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/options_for_select options_for_select}
|
9
|
+
#
|
10
|
+
# @example Input is used as follows
|
11
|
+
# f.input :fav_book, :as => :datalist, :collection => Book.pluck(:name)
|
12
|
+
#
|
13
|
+
class DatalistInput
|
14
|
+
include Base
|
15
|
+
include Base::Stringish
|
16
|
+
include Base::Collections
|
17
|
+
|
18
|
+
def to_html
|
19
|
+
@name = input_html_options[:id].gsub(/_id$/, "")
|
20
|
+
input_wrapping do
|
21
|
+
label_html <<
|
22
|
+
builder.text_field(method, input_html_options) << # standard input
|
23
|
+
data_list_html # append new datalist element
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def input_html_options
|
28
|
+
super.merge(:list => html_id_of_datalist)
|
29
|
+
end
|
30
|
+
|
31
|
+
def html_id_of_datalist
|
32
|
+
"#{@name}_datalist"
|
33
|
+
end
|
34
|
+
|
35
|
+
def data_list_html
|
36
|
+
html = builder.template.options_for_select(collection)
|
37
|
+
builder.template.content_tag(:datalist,html, { :id => html_id_of_datalist }, false)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module Inputs
|
3
|
+
|
4
|
+
# Outputs a simple `<label>` with a HTML5 `<input type="date">` wrapped in the standard
|
5
|
+
# `<li>` wrapper. This is an alternative to `:date_select` for `:date`, `:time`, `:datetime`
|
6
|
+
# database columns. You can use this input with `:as => :date_picker`.
|
7
|
+
#
|
8
|
+
# *Please note:* Formtastic only provides suitable markup for a date picker, but does not supply
|
9
|
+
# any additional CSS or Javascript to render calendar-style date pickers. Browsers that support
|
10
|
+
# this input type (such as Mobile Webkit and Opera on the desktop) will render a native widget.
|
11
|
+
# Browsers that don't will default to a plain text field`<input type="text">` and can be
|
12
|
+
# poly-filled with some Javascript and a UI library of your choice.
|
13
|
+
#
|
14
|
+
# @example Full form context and output
|
15
|
+
#
|
16
|
+
# <%= semantic_form_for(@post) do |f| %>
|
17
|
+
# <%= f.inputs do %>
|
18
|
+
# <%= f.input :publish_at, :as => :date_picker %>
|
19
|
+
# <% end %>
|
20
|
+
# <% end %>
|
21
|
+
#
|
22
|
+
# <form...>
|
23
|
+
# <fieldset>
|
24
|
+
# <ol>
|
25
|
+
# <li class="string">
|
26
|
+
# <label for="post_publish_at">First name</label>
|
27
|
+
# <input type="date" id="post_publish_at" name="post[publish_at]">
|
28
|
+
# </li>
|
29
|
+
# </ol>
|
30
|
+
# </fieldset>
|
31
|
+
# </form>
|
32
|
+
#
|
33
|
+
# @example Setting the size (defaults to 10 for YYYY-MM-DD)
|
34
|
+
# <%= f.input :publish_at, :as => :date_picker, :size => 20 %>
|
35
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :size => 20 } %>
|
36
|
+
#
|
37
|
+
# @example Setting the maxlength (defaults to 10 for YYYY-MM-DD)
|
38
|
+
# <%= f.input :publish_at, :as => :date_picker, :maxlength => 20 %>
|
39
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :maxlength => 20 } %>
|
40
|
+
#
|
41
|
+
# @example Setting the value (defaults to YYYY-MM-DD for Date and Time objects, otherwise renders string)
|
42
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :value => "1970-01-01" } %>
|
43
|
+
#
|
44
|
+
# @example Setting the step attribute (defaults to 1)
|
45
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => 7 %>
|
46
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :step => 7 } %>
|
47
|
+
#
|
48
|
+
# @example Setting the step attribute with a macro
|
49
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :day %>
|
50
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :week %>
|
51
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :seven_days %>
|
52
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :fortnight %>
|
53
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :two_weeks %>
|
54
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :four_weeks %>
|
55
|
+
# <%= f.input :publish_at, :as => :date_picker, :step => :thirty_days %>
|
56
|
+
#
|
57
|
+
# @example Setting the min attribute
|
58
|
+
# <%= f.input :publish_at, :as => :date_picker, :min => "2012-01-01" %>
|
59
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :min => "2012-01-01" } %>
|
60
|
+
#
|
61
|
+
# @example Setting the max attribute
|
62
|
+
# <%= f.input :publish_at, :as => :date_picker, :max => "2012-12-31" %>
|
63
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :max => "2012-12-31" } %>
|
64
|
+
#
|
65
|
+
# @example Setting the placeholder attribute
|
66
|
+
# <%= f.input :publish_at, :as => :date_picker, :placeholder => 20 %>
|
67
|
+
# <%= f.input :publish_at, :as => :date_picker, :input_html => { :placeholder => "YYYY-MM-DD" } %>
|
68
|
+
#
|
69
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
70
|
+
class DatePickerInput
|
71
|
+
include Base
|
72
|
+
include Base::Stringish
|
73
|
+
include Base::DatetimePickerish
|
74
|
+
|
75
|
+
def html_input_type
|
76
|
+
"date"
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_size
|
80
|
+
10
|
81
|
+
end
|
82
|
+
|
83
|
+
def value
|
84
|
+
return options[:input_html][:value] if options[:input_html] && options[:input_html].key?(:value)
|
85
|
+
val = object.send(method)
|
86
|
+
return Date.new(val.year, val.month, val.day).to_s if val.is_a?(Time)
|
87
|
+
return val if val.nil?
|
88
|
+
val.to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -3,7 +3,7 @@ module Formtastic
|
|
3
3
|
# Outputs a series of select boxes for the fragments that make up a date (year, month, day).
|
4
4
|
#
|
5
5
|
# @see Formtastic::Inputs::Base::Timeish Timeish module for documentation of date, time and datetime input options.
|
6
|
-
class
|
6
|
+
class DateSelectInput
|
7
7
|
include Base
|
8
8
|
include Base::Timeish
|
9
9
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module Inputs
|
3
|
+
|
4
|
+
# Outputs a simple `<label>` with a HTML5 `<input type="datetime-local">` (or
|
5
|
+
# `<input type="datetime">`) wrapped in the standard `<li>` wrapper. This is an alternative to
|
6
|
+
# `:date_select` for `:date`, `:time`, `:datetime` database columns. You can use this input with
|
7
|
+
# `:as => :datetime_picker`.
|
8
|
+
#
|
9
|
+
# *Please note:* Formtastic only provides suitable markup for a date picker, but does not supply
|
10
|
+
# any additional CSS or Javascript to render calendar-style date pickers. Browsers that support
|
11
|
+
# this input type (such as Mobile Webkit and Opera on the desktop) will render a native widget.
|
12
|
+
# Browsers that don't will default to a plain text field`<input type="text">` and can be
|
13
|
+
# poly-filled with some Javascript and a UI library of your choice.
|
14
|
+
#
|
15
|
+
# @example Full form context and output
|
16
|
+
#
|
17
|
+
# <%= semantic_form_for(@post) do |f| %>
|
18
|
+
# <%= f.inputs do %>
|
19
|
+
# <%= f.input :publish_at, :as => :datetime_picker %>
|
20
|
+
# <% end %>
|
21
|
+
# <% end %>
|
22
|
+
#
|
23
|
+
# <form...>
|
24
|
+
# <fieldset>
|
25
|
+
# <ol>
|
26
|
+
# <li class="string">
|
27
|
+
# <label for="post_publish_at">First name</label>
|
28
|
+
# <input type="date" id="post_publish_at" name="post[publish_at]">
|
29
|
+
# </li>
|
30
|
+
# </ol>
|
31
|
+
# </fieldset>
|
32
|
+
# </form>
|
33
|
+
#
|
34
|
+
# @example Setting the size (defaults to 16 for YYYY-MM-DD HH:MM)
|
35
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :size => 20 %>
|
36
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :size => 20 } %>
|
37
|
+
#
|
38
|
+
# @example Setting the maxlength (defaults to 16 for YYYY-MM-DD HH:MM)
|
39
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :maxlength => 20 %>
|
40
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :maxlength => 20 } %>
|
41
|
+
#
|
42
|
+
# @example Setting the value (defaults to YYYY-MM-DD HH:MM for Date and Time objects, otherwise renders string)
|
43
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :value => "1970-01-01 00:00" } %>
|
44
|
+
#
|
45
|
+
# @example Setting the step attribute (defaults to 1)
|
46
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => 60 %>
|
47
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :step => 60 } %>
|
48
|
+
#
|
49
|
+
# @example Setting the step attribute with a macro
|
50
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :second %>
|
51
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :minute %>
|
52
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :quarter_hour %>
|
53
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :fifteen_minutes %>
|
54
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :half_hour %>
|
55
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :thirty_minutes %>
|
56
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :hour %>
|
57
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :step => :sixty_minutes %>
|
58
|
+
#
|
59
|
+
# @example Setting the min attribute
|
60
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :min => "2012-01-01 09:00" %>
|
61
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :min => "2012-01-01 09:00" } %>
|
62
|
+
#
|
63
|
+
# @example Setting the max attribute
|
64
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :max => "2012-12-31 16:00" %>
|
65
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :max => "2012-12-31 16:00" } %>
|
66
|
+
#
|
67
|
+
# @example Setting the placeholder attribute
|
68
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :placeholder => "YYYY-MM-DD HH:MM" %>
|
69
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :input_html => { :placeholder => "YYYY-MM-DD HH:MM" } %>
|
70
|
+
#
|
71
|
+
# @example Using `type=datetime-local` with `:local` option (this is the default, and recommended for browser support on iOS7 and Chrome)
|
72
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :local => true %>
|
73
|
+
#
|
74
|
+
# @example Using `type=datetime` with `:local` option (not recommended)
|
75
|
+
# <%= f.input :publish_at, :as => :datetime_picker, :local => false %>
|
76
|
+
#
|
77
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
78
|
+
class DatetimePickerInput
|
79
|
+
include Base
|
80
|
+
include Base::Stringish
|
81
|
+
include Base::DatetimePickerish
|
82
|
+
|
83
|
+
def html_input_type
|
84
|
+
options[:local] = true unless options.key?(:local)
|
85
|
+
options[:local] ? "datetime-local" : "datetime"
|
86
|
+
end
|
87
|
+
|
88
|
+
def default_size
|
89
|
+
16
|
90
|
+
end
|
91
|
+
|
92
|
+
def value
|
93
|
+
return options[:input_html][:value] if options[:input_html] && options[:input_html].key?(:value)
|
94
|
+
val = object.send(method)
|
95
|
+
return val.strftime("%Y-%m-%dT%H:%M:%S") if val.is_a?(Time)
|
96
|
+
return "#{val.year}-#{val.month}-#{val.day}T00:00:00" if val.is_a?(Date)
|
97
|
+
return val if val.nil?
|
98
|
+
val.to_s
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -4,7 +4,7 @@ module Formtastic
|
|
4
4
|
# Outputs a series of select boxes for the fragments that make up a date and time (year, month, day, hour, minute, second).
|
5
5
|
#
|
6
6
|
# @see Formtastic::Inputs::Base::Timeish Timeish module for documentation of date, time and datetime input options.
|
7
|
-
class
|
7
|
+
class DatetimeSelectInput
|
8
8
|
include Base
|
9
9
|
include Base::Timeish
|
10
10
|
end
|
@@ -20,7 +20,7 @@ module Formtastic
|
|
20
20
|
# <form...>
|
21
21
|
# <fieldset>
|
22
22
|
# <ol>
|
23
|
-
# <li class="
|
23
|
+
# <li class="file">
|
24
24
|
# <label for="user_avatar">Avatar</label>
|
25
25
|
# <input type="file" id="user_avatar" name="user[avatar]">
|
26
26
|
# </li>
|
@@ -29,7 +29,7 @@ module Formtastic
|
|
29
29
|
# </form>
|
30
30
|
#
|
31
31
|
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
32
|
-
class FileInput
|
32
|
+
class FileInput
|
33
33
|
include Base
|
34
34
|
def to_html
|
35
35
|
input_wrapping do
|
@@ -31,12 +31,8 @@ module Formtastic
|
|
31
31
|
class HiddenInput
|
32
32
|
include Base
|
33
33
|
|
34
|
-
# Override to include :value set directly from options hash. The :value set in :input_html
|
35
|
-
# hash will be preferred over :value set directly in the options.
|
36
|
-
#
|
37
|
-
# @todo this is inconsistent with all other inputs, deprecate and remove
|
38
34
|
def input_html_options
|
39
|
-
|
35
|
+
super.merge(:required => nil).merge(:autofocus => nil)
|
40
36
|
end
|
41
37
|
|
42
38
|
def to_html
|
@@ -63,4 +59,4 @@ module Formtastic
|
|
63
59
|
|
64
60
|
end
|
65
61
|
end
|
66
|
-
end
|
62
|
+
end
|
@@ -20,7 +20,7 @@ module Formtastic
|
|
20
20
|
#
|
21
21
|
# * a `:string` input (where you want to force the user to choose from a few specific strings rather than entering anything)
|
22
22
|
# * a `:boolean` checkbox input (where the user could choose yes or no, rather than checking a box)
|
23
|
-
# * a `:
|
23
|
+
# * a `:date_select`, `:time_select` or `:datetime_select` input (where the user could choose from a small set of pre-determined dates)
|
24
24
|
# * a `:number` input (where the user could choose from a small set of pre-defined numbers)
|
25
25
|
# * a `:time_zone` input (where you want to provide your own small set of choices instead of relying on Rails)
|
26
26
|
# * a `:country` input (where you want to provide a small set of choices, no need for a plugin really)
|
@@ -31,10 +31,13 @@ module Formtastic
|
|
31
31
|
# `Section.all` for a `Post` form with an input for a `belongs_to :section` association.
|
32
32
|
# You can override or customise this collection through the `:collection` option (see examples).
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
34
|
+
# For radio inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
|
35
|
+
# load in your enum options to be used as the radio button choices. This can be overridden with
|
36
|
+
# the `:collection` option, or augmented with I18n translations. See examples below.
|
37
|
+
#
|
38
|
+
# The way on which Formtastic renders the `value` attribute and label for each choice in the `:collection` is
|
39
|
+
# customisable (see examples below). When not provided, we fall back to a list of methods to try on each
|
40
|
+
# object such as `:to_label`, `:name` and `:to_s`, which are defined in the configurations
|
38
41
|
# `collection_label_methods` and `collection_value_methods`.
|
39
42
|
#
|
40
43
|
# @example Basic `belongs_to` example with full form context
|
@@ -78,30 +81,17 @@ module Formtastic
|
|
78
81
|
# <%= f.input :author, :as => :radio, :collection => @authors %>
|
79
82
|
# <%= f.input :author, :as => :radio, :collection => Author.all %>
|
80
83
|
# <%= f.input :author, :as => :radio, :collection => Author.some_named_scope %>
|
84
|
+
# <%= f.input :author, :as => :radio, :collection => Author.pluck(:full_name, :id) %>
|
85
|
+
# <%= f.input :author, :as => :radio, :collection => Author.pluck(Arel.sql("CONCAT(`first_name`, ' ', `last_name`)"), :id)) %>
|
81
86
|
# <%= f.input :author, :as => :radio, :collection => [Author.find_by_login("justin"), Category.find_by_name("kate")] %>
|
82
87
|
# <%= f.input :author, :as => :radio, :collection => ["Justin", "Kate"] %>
|
83
88
|
# <%= f.input :author, :as => :radio, :collection => [["Justin", "justin"], ["Kate", "kate"]] %>
|
84
89
|
# <%= f.input :author, :as => :radio, :collection => [["Justin", "1"], ["Kate", "3"]] %>
|
85
90
|
# <%= f.input :author, :as => :radio, :collection => [["Justin", 1], ["Kate", 3]] %>
|
91
|
+
# <%= f.input :author, :as => :radio, :collection => [["Justin", :justin], ["Kate", :kate]] %>
|
92
|
+
# <%= f.input :author, :as => :radio, :collection => [:justin, :kate] %>
|
86
93
|
# <%= f.input :author, :as => :radio, :collection => 1..5 %>
|
87
94
|
#
|
88
|
-
# @example The `:member_label` can be used to call a different method (or a Proc) on each object in the collection for rendering the label text (it'll try the methods like `to_s` in `collection_label_methods` config by default)
|
89
|
-
# <%= f.input :author, :as => :radio, :member_label => :name %>
|
90
|
-
# <%= f.input :author, :as => :radio, :member_label => :name_with_post_count
|
91
|
-
# <%= f.input :author, :as => :radio, :member_label => Proc.new { |a| "#{c.name} (#{pluralize("post", a.posts.count)})" }
|
92
|
-
#
|
93
|
-
# @example `:member_label` can be used with a helper method (both examples have the same result)
|
94
|
-
# <%= f.input :author, :as => :radio, :member_label => method(:fancy_label)
|
95
|
-
# <%= f.input :author, :as => :radio, :member_label => Proc.new { |author| fancy_label(author) }
|
96
|
-
#
|
97
|
-
# @example The `:member_value` can be used to call a different method (or a Proc) on each object in the collection for rendering the value for each checkbox (it'll try the methods like `id` in `collection_value_methods` config by default)
|
98
|
-
# <%= f.input :author, :as => :radio, :member_value => :login %>
|
99
|
-
# <%= f.input :author, :as => :radio, :member_value => Proc.new { |c| c.full_name.downcase.underscore }
|
100
|
-
#
|
101
|
-
# @example `:member_value` can be used with a helper method (both examples have the same result)
|
102
|
-
# <%= f.input :author, :as => :radio, :member_value => method(:some_helper)
|
103
|
-
# <%= f.input :author, :as => :radio, :member_value => Proc.new { |author| some_helper(author) }
|
104
|
-
#
|
105
95
|
# @example Set HTML attributes on each `<input type="radio">` tag with `:input_html`
|
106
96
|
# <%= f.input :author, :as => :radio, :input_html => { :size => 20, :multiple => true, :class => "special" } %>
|
107
97
|
#
|
@@ -114,6 +104,22 @@ module Formtastic
|
|
114
104
|
# @example Set HTML options on a specific radio input option with a 3rd element in the array for a collection member
|
115
105
|
# <%= f.input :author, :as => :radio, :collection => [["Test", 'test'], ["Try", "try", {:disabled => true}]]
|
116
106
|
#
|
107
|
+
# @example Using ActiveRecord enum attribute with i18n translation:
|
108
|
+
# # post.rb
|
109
|
+
# class Post < ActiveRecord::Base
|
110
|
+
# enum :status => [ :active, :archived ]
|
111
|
+
# end
|
112
|
+
# # en.yml
|
113
|
+
# en:
|
114
|
+
# activerecord:
|
115
|
+
# attributes:
|
116
|
+
# post:
|
117
|
+
# statuses:
|
118
|
+
# active: I am active!
|
119
|
+
# archived: I am archived!
|
120
|
+
# # form
|
121
|
+
# <%= f.input :status, :as => :radio %>
|
122
|
+
#
|
117
123
|
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
118
124
|
# @see Formtastic::Inputs::RadioInput as an alternative for `belongs_to` associations
|
119
125
|
#
|
@@ -8,6 +8,7 @@ module Formtastic
|
|
8
8
|
# This is the default input choice when:
|
9
9
|
#
|
10
10
|
# * the database column type is an `:integer` and there is an association (`belongs_to`)
|
11
|
+
# * the database column type is an `:integer` and there is an enum defined (`enum`)
|
11
12
|
# * the database column type is a `:string` and the `:collection` option is used
|
12
13
|
# * there an object with an association, but no database column on the object (`has_many`, etc)
|
13
14
|
# * there is no object and the `:collection` option is used
|
@@ -17,7 +18,7 @@ module Formtastic
|
|
17
18
|
#
|
18
19
|
# * a `:string` input (where you want to force the user to choose from a few specific strings rather than entering anything)
|
19
20
|
# * a `:boolean` checkbox input (where the user could choose yes or no, rather than checking a box)
|
20
|
-
# * a `:
|
21
|
+
# * a `:date_select`, `:time_select` or `:datetime_select` input (where the user could choose from pre-selected dates)
|
21
22
|
# * a `:number` input (where the user could choose from a set of pre-defined numbers)
|
22
23
|
# * a `:time_zone` input (where you want to provide your own set of choices instead of relying on Rails)
|
23
24
|
# * a `:country` input (no need for a plugin really)
|
@@ -38,6 +39,13 @@ module Formtastic
|
|
38
39
|
# `:to_s`, which are defined in the configurations `collection_label_methods` and
|
39
40
|
# `collection_value_methods` (see examples below).
|
40
41
|
#
|
42
|
+
# For select inputs that map to ActiveRecord `enum` attributes, Formtastic will automatically
|
43
|
+
# load in your enum options to be used as the select's options. This can be overridden with
|
44
|
+
# the `:collection` option, or augmented with I18n translations. See examples below.
|
45
|
+
# An error is raised if you try to render a multi-select with an enum, as ActiveRecord can
|
46
|
+
# only store one choice in the database.
|
47
|
+
#
|
48
|
+
#
|
41
49
|
# @example Basic `belongs_to` example with full form context
|
42
50
|
#
|
43
51
|
# <%= semantic_form_for @post do |f| %>
|
@@ -94,6 +102,8 @@ module Formtastic
|
|
94
102
|
# <%= f.input :author, :as => :select, :collection => @authors %>
|
95
103
|
# <%= f.input :author, :as => :select, :collection => Author.all %>
|
96
104
|
# <%= f.input :author, :as => :select, :collection => Author.some_named_scope %>
|
105
|
+
# <%= f.input :author, :as => :select, :collection => Author.pluck(:full_name, :id) %>
|
106
|
+
# <%= f.input :author, :as => :select, :collection => Author.pluck(Arel.sql("CONCAT(`first_name`, ' ', `last_name`)"), :id)) %>
|
97
107
|
# <%= f.input :author, :as => :select, :collection => [Author.find_by_login("justin"), Category.find_by_name("kate")] %>
|
98
108
|
# <%= f.input :author, :as => :select, :collection => ["Justin", "Kate"] %>
|
99
109
|
# <%= f.input :author, :as => :select, :collection => [["Justin", "justin"], ["Kate", "kate"]] %>
|
@@ -106,15 +116,6 @@ module Formtastic
|
|
106
116
|
# <%= f.input :author, :as => :select, :collection => grouped_options_for_select(...) %>
|
107
117
|
# <%= f.input :author, :as => :select, :collection => time_zone_options_for_select(...) %>
|
108
118
|
#
|
109
|
-
# @example The `:member_label` can be used to call a different method (or a Proc) on each object in the collection for rendering the label text (it'll try the methods like `to_s` in `collection_label_methods` config by default)
|
110
|
-
# <%= f.input :author, :as => :select, :member_label => :name %>
|
111
|
-
# <%= f.input :author, :as => :select, :member_label => :name_with_post_count %>
|
112
|
-
# <%= f.input :author, :as => :select, :member_label => Proc.new { |a| "#{c.name} (#{pluralize("post", a.posts.count)})" } %>
|
113
|
-
#
|
114
|
-
# @example The `:member_value` can be used to call a different method (or a Proc) on each object in the collection for rendering the value for each checkbox (it'll try the methods like `id` in `collection_value_methods` config by default)
|
115
|
-
# <%= f.input :author, :as => :select, :member_value => :login %>
|
116
|
-
# <%= f.input :author, :as => :select, :member_value => Proc.new { |c| c.full_name.downcase.underscore } %>
|
117
|
-
#
|
118
119
|
# @example Set HTML attributes on the `<select>` tag with `:input_html`
|
119
120
|
# <%= f.input :authors, :as => :select, :input_html => { :size => 20, :multiple => true, :class => "special" } %>
|
120
121
|
#
|
@@ -131,9 +132,21 @@ module Formtastic
|
|
131
132
|
# <%= f.input :author, :as => :select, :prompt => true %> => <option value="">Please select</option>
|
132
133
|
# <%= f.input :author, :as => :select, :prompt => "Please select an author" %>
|
133
134
|
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
135
|
+
# @example Using ActiveRecord enum attribute with i18n translation:
|
136
|
+
# # post.rb
|
137
|
+
# class Post < ActiveRecord::Base
|
138
|
+
# enum :status => [ :active, :archived ]
|
139
|
+
# end
|
140
|
+
# # en.yml
|
141
|
+
# en:
|
142
|
+
# activerecord:
|
143
|
+
# attributes:
|
144
|
+
# post:
|
145
|
+
# statuses:
|
146
|
+
# active: I am active!
|
147
|
+
# archived: I am archived!
|
148
|
+
# # form
|
149
|
+
# <%= f.input :status, :as => :select %>
|
137
150
|
#
|
138
151
|
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
139
152
|
# @see Formtastic::Inputs::CheckBoxesInput CheckBoxesInput as an alternative for `has_many` and `has_and_belongs_to_many` associations
|
@@ -143,13 +156,16 @@ module Formtastic
|
|
143
156
|
class SelectInput
|
144
157
|
include Base
|
145
158
|
include Base::Collections
|
146
|
-
|
159
|
+
|
160
|
+
def initialize(*args)
|
161
|
+
super
|
162
|
+
raise Formtastic::UnsupportedEnumCollection if collection_from_enum? && multiple?
|
163
|
+
end
|
147
164
|
|
148
165
|
def to_html
|
149
166
|
input_wrapping do
|
150
|
-
hidden_input <<
|
151
167
|
label_html <<
|
152
|
-
|
168
|
+
select_html
|
153
169
|
end
|
154
170
|
end
|
155
171
|
|
@@ -157,31 +173,10 @@ module Formtastic
|
|
157
173
|
builder.select(input_name, collection, input_options, input_html_options)
|
158
174
|
end
|
159
175
|
|
160
|
-
def grouped_select_html
|
161
|
-
builder.grouped_collection_select(
|
162
|
-
input_name,
|
163
|
-
grouped_collection,
|
164
|
-
group_association,
|
165
|
-
group_label_method,
|
166
|
-
value_method,
|
167
|
-
label_method,
|
168
|
-
input_options,
|
169
|
-
input_html_options
|
170
|
-
)
|
171
|
-
end
|
172
|
-
|
173
176
|
def include_blank
|
174
177
|
options.key?(:include_blank) ? options[:include_blank] : (single? && builder.include_blank_for_select_by_default)
|
175
178
|
end
|
176
179
|
|
177
|
-
def hidden_input
|
178
|
-
if multiple?
|
179
|
-
template.hidden_field_tag(input_html_options_name_multiple, '', :id => nil)
|
180
|
-
else
|
181
|
-
"".html_safe
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
180
|
def prompt?
|
186
181
|
!!options[:prompt]
|
187
182
|
end
|
@@ -195,7 +190,7 @@ module Formtastic
|
|
195
190
|
end
|
196
191
|
|
197
192
|
def input_html_options
|
198
|
-
extra_input_html_options.merge(super)
|
193
|
+
extra_input_html_options.merge(super.reject {|k,v| k==:name && v.nil?} )
|
199
194
|
end
|
200
195
|
|
201
196
|
def extra_input_html_options
|
@@ -203,6 +198,8 @@ module Formtastic
|
|
203
198
|
:multiple => multiple?,
|
204
199
|
:name => multiple? ? input_html_options_name_multiple : input_html_options_name
|
205
200
|
}
|
201
|
+
|
202
|
+
|
206
203
|
end
|
207
204
|
|
208
205
|
def input_html_options_name
|
@@ -235,4 +232,4 @@ module Formtastic
|
|
235
232
|
|
236
233
|
end
|
237
234
|
end
|
238
|
-
end
|
235
|
+
end
|