formtastic 1.2.4 → 3.1.5
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +46 -0
- data/.yardopts +1 -0
- data/Appraisals +43 -0
- data/CHANGELOG +54 -0
- data/DEPRECATIONS +52 -0
- data/Gemfile +3 -0
- data/README.md +629 -0
- data/RELEASE_PROCESS +6 -0
- data/Rakefile +35 -0
- data/app/assets/stylesheets/formtastic.css +289 -0
- data/app/assets/stylesheets/formtastic_ie6.css +33 -0
- data/app/assets/stylesheets/formtastic_ie7.css +23 -0
- data/formtastic.gemspec +42 -0
- data/gemfiles/rails_3.2.gemfile +9 -0
- data/gemfiles/rails_4.0.4.gemfile +8 -0
- data/gemfiles/rails_4.1.gemfile +8 -0
- data/gemfiles/rails_4.2.gemfile +8 -0
- data/gemfiles/rails_4.gemfile +8 -0
- data/gemfiles/rails_5.0.gemfile +8 -0
- data/gemfiles/rails_edge.gemfile +15 -0
- data/lib/formtastic.rb +40 -1945
- data/lib/formtastic/action_class_finder.rb +18 -0
- data/lib/formtastic/actions.rb +11 -0
- data/lib/formtastic/actions/base.rb +156 -0
- data/lib/formtastic/actions/button_action.rb +67 -0
- data/lib/formtastic/actions/buttonish.rb +17 -0
- data/lib/formtastic/actions/input_action.rb +70 -0
- data/lib/formtastic/actions/link_action.rb +88 -0
- data/lib/formtastic/deprecation.rb +42 -0
- data/lib/formtastic/engine.rb +11 -0
- data/lib/formtastic/form_builder.rb +124 -0
- data/lib/formtastic/helpers.rb +16 -0
- data/lib/formtastic/helpers/action_helper.rb +162 -0
- data/lib/formtastic/helpers/actions_helper.rb +168 -0
- data/lib/formtastic/helpers/enum.rb +13 -0
- data/lib/formtastic/helpers/errors_helper.rb +81 -0
- data/lib/formtastic/helpers/fieldset_wrapper.rb +80 -0
- data/lib/formtastic/helpers/file_column_detection.rb +16 -0
- data/lib/formtastic/helpers/form_helper.rb +203 -0
- data/lib/formtastic/helpers/input_helper.rb +407 -0
- data/lib/formtastic/helpers/inputs_helper.rb +411 -0
- data/lib/formtastic/helpers/reflection.rb +37 -0
- data/lib/formtastic/html_attributes.rb +32 -0
- data/lib/formtastic/i18n.rb +4 -2
- data/lib/formtastic/input_class_finder.rb +18 -0
- data/lib/formtastic/inputs.rb +39 -0
- data/lib/formtastic/inputs/base.rb +76 -0
- data/lib/formtastic/inputs/base/associations.rb +31 -0
- data/lib/formtastic/inputs/base/choices.rb +108 -0
- data/lib/formtastic/inputs/base/collections.rb +159 -0
- data/lib/formtastic/inputs/base/database.rb +22 -0
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
- data/lib/formtastic/inputs/base/errors.rb +58 -0
- data/lib/formtastic/inputs/base/fileish.rb +23 -0
- data/lib/formtastic/inputs/base/hints.rb +31 -0
- data/lib/formtastic/inputs/base/html.rb +53 -0
- data/lib/formtastic/inputs/base/labelling.rb +52 -0
- data/lib/formtastic/inputs/base/naming.rb +42 -0
- data/lib/formtastic/inputs/base/numeric.rb +50 -0
- data/lib/formtastic/inputs/base/options.rb +17 -0
- data/lib/formtastic/inputs/base/placeholder.rb +17 -0
- data/lib/formtastic/inputs/base/stringish.rb +38 -0
- data/lib/formtastic/inputs/base/timeish.rb +241 -0
- data/lib/formtastic/inputs/base/validations.rb +215 -0
- data/lib/formtastic/inputs/base/wrapping.rb +50 -0
- data/lib/formtastic/inputs/boolean_input.rb +118 -0
- data/lib/formtastic/inputs/check_boxes_input.rb +197 -0
- data/lib/formtastic/inputs/color_input.rb +42 -0
- data/lib/formtastic/inputs/country_input.rb +86 -0
- data/lib/formtastic/inputs/datalist_input.rb +41 -0
- data/lib/formtastic/inputs/date_picker_input.rb +93 -0
- data/lib/formtastic/inputs/date_select_input.rb +34 -0
- data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
- data/lib/formtastic/inputs/datetime_select_input.rb +12 -0
- data/lib/formtastic/inputs/email_input.rb +41 -0
- data/lib/formtastic/inputs/file_input.rb +42 -0
- data/lib/formtastic/inputs/hidden_input.rb +62 -0
- data/lib/formtastic/inputs/number_input.rb +88 -0
- data/lib/formtastic/inputs/password_input.rb +41 -0
- data/lib/formtastic/inputs/phone_input.rb +42 -0
- data/lib/formtastic/inputs/radio_input.rb +163 -0
- data/lib/formtastic/inputs/range_input.rb +95 -0
- data/lib/formtastic/inputs/search_input.rb +41 -0
- data/lib/formtastic/inputs/select_input.rb +235 -0
- data/lib/formtastic/inputs/string_input.rb +36 -0
- data/lib/formtastic/inputs/text_input.rb +48 -0
- data/lib/formtastic/inputs/time_picker_input.rb +99 -0
- data/lib/formtastic/inputs/time_select_input.rb +38 -0
- data/lib/formtastic/inputs/time_zone_input.rb +58 -0
- data/lib/formtastic/inputs/url_input.rb +41 -0
- data/lib/formtastic/localized_string.rb +17 -0
- data/lib/formtastic/localizer.rb +152 -0
- data/lib/formtastic/namespaced_class_finder.rb +99 -0
- data/lib/formtastic/util.rb +35 -16
- data/lib/formtastic/version.rb +3 -0
- data/lib/generators/formtastic/form/form_generator.rb +64 -37
- data/lib/generators/formtastic/input/input_generator.rb +46 -0
- data/lib/generators/formtastic/install/install_generator.rb +13 -5
- data/lib/generators/templates/_form.html.erb +10 -4
- data/lib/generators/templates/_form.html.haml +8 -4
- data/lib/generators/templates/_form.html.slim +8 -0
- data/lib/generators/templates/formtastic.rb +77 -44
- data/lib/generators/templates/input.rb +19 -0
- data/lib/locale/en.yml +3 -0
- data/sample/basic_inputs.html +224 -0
- data/sample/config.ru +69 -0
- data/sample/index.html +14 -0
- data/spec/action_class_finder_spec.rb +12 -0
- data/spec/actions/button_action_spec.rb +63 -0
- data/spec/actions/generic_action_spec.rb +521 -0
- data/spec/actions/input_action_spec.rb +59 -0
- data/spec/actions/link_action_spec.rb +92 -0
- data/spec/builder/custom_builder_spec.rb +116 -0
- data/spec/builder/error_proc_spec.rb +27 -0
- data/spec/builder/semantic_fields_for_spec.rb +142 -0
- data/spec/fast_spec_helper.rb +12 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +131 -0
- data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +47 -0
- data/spec/helpers/action_helper_spec.rb +19 -0
- data/spec/helpers/actions_helper_spec.rb +143 -0
- data/spec/helpers/form_helper_spec.rb +218 -0
- data/spec/helpers/input_helper_spec.rb +6 -0
- data/spec/helpers/inputs_helper_spec.rb +655 -0
- data/spec/helpers/namespaced_action_helper_spec.rb +43 -0
- data/spec/helpers/namespaced_input_helper_spec.rb +36 -0
- data/spec/helpers/reflection_helper_spec.rb +32 -0
- data/spec/helpers/semantic_errors_helper_spec.rb +112 -0
- data/spec/i18n_spec.rb +210 -0
- 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 +342 -0
- data/spec/inputs/boolean_input_spec.rb +254 -0
- data/spec/inputs/check_boxes_input_spec.rb +546 -0
- data/spec/inputs/color_input_spec.rb +97 -0
- data/spec/inputs/country_input_spec.rb +133 -0
- data/spec/inputs/custom_input_spec.rb +55 -0
- 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 +235 -0
- data/spec/inputs/datetime_picker_input_spec.rb +490 -0
- data/spec/inputs/datetime_select_input_spec.rb +193 -0
- data/spec/inputs/email_input_spec.rb +85 -0
- data/spec/inputs/file_input_spec.rb +89 -0
- data/spec/inputs/hidden_input_spec.rb +135 -0
- data/spec/inputs/include_blank_spec.rb +78 -0
- data/spec/inputs/label_spec.rb +149 -0
- data/spec/inputs/number_input_spec.rb +815 -0
- data/spec/inputs/password_input_spec.rb +99 -0
- data/spec/inputs/phone_input_spec.rb +85 -0
- data/spec/inputs/placeholder_spec.rb +71 -0
- data/spec/inputs/radio_input_spec.rb +328 -0
- data/spec/inputs/range_input_spec.rb +505 -0
- data/spec/inputs/readonly_spec.rb +50 -0
- data/spec/inputs/search_input_spec.rb +84 -0
- data/spec/inputs/select_input_spec.rb +615 -0
- data/spec/inputs/string_input_spec.rb +260 -0
- data/spec/inputs/text_input_spec.rb +187 -0
- data/spec/inputs/time_picker_input_spec.rb +455 -0
- data/spec/inputs/time_select_input_spec.rb +248 -0
- data/spec/inputs/time_zone_input_spec.rb +143 -0
- data/spec/inputs/url_input_spec.rb +85 -0
- data/spec/inputs/with_options_spec.rb +43 -0
- data/spec/localizer_spec.rb +130 -0
- data/spec/namespaced_class_finder_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +525 -0
- data/spec/support/custom_macros.rb +564 -0
- data/spec/support/deprecation.rb +6 -0
- data/spec/support/shared_examples.rb +1313 -0
- data/spec/support/specialized_class_finder_shared_example.rb +27 -0
- data/spec/support/test_environment.rb +31 -0
- data/spec/util_spec.rb +66 -0
- metadata +434 -161
- data/README.textile +0 -682
- data/generators/form/USAGE +0 -16
- data/generators/form/form_generator.rb +0 -111
- data/generators/formtastic/formtastic_generator.rb +0 -26
- data/init.rb +0 -5
- data/lib/formtastic/layout_helper.rb +0 -12
- data/lib/formtastic/railtie.rb +0 -14
- data/lib/generators/templates/formtastic.css +0 -145
- data/lib/generators/templates/formtastic_changes.css +0 -14
- data/lib/generators/templates/rails2/_form.html.erb +0 -5
- data/lib/generators/templates/rails2/_form.html.haml +0 -4
- data/rails/init.rb +0 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
module Inputs
|
|
3
|
+
module Base
|
|
4
|
+
# @todo relies on `dom_id`, `required?`, `optional`, `errors?`, `association_primary_key` & `sanitized_method_name` methods from another module
|
|
5
|
+
module Wrapping
|
|
6
|
+
|
|
7
|
+
# Override this method if you want to change the display order (for example, rendering the
|
|
8
|
+
# errors before the body of the input).
|
|
9
|
+
def input_wrapping(&block)
|
|
10
|
+
template.content_tag(:li,
|
|
11
|
+
[template.capture(&block), error_html, hint_html].join("\n").html_safe,
|
|
12
|
+
wrapper_html_options
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def wrapper_html_options
|
|
17
|
+
opts = wrapper_html_options_raw
|
|
18
|
+
opts[:class] = wrapper_classes
|
|
19
|
+
opts[:id] = wrapper_dom_id unless opts.has_key? :id
|
|
20
|
+
opts
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def wrapper_html_options_raw
|
|
24
|
+
(options[:wrapper_html] || {}).dup
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def wrapper_classes_raw
|
|
28
|
+
[*wrapper_html_options_raw[:class]]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def wrapper_classes
|
|
32
|
+
classes = wrapper_classes_raw
|
|
33
|
+
classes << as
|
|
34
|
+
classes << "input"
|
|
35
|
+
classes << "error" if errors?
|
|
36
|
+
classes << "optional" if optional?
|
|
37
|
+
classes << "required" if required?
|
|
38
|
+
classes << "autofocus" if autofocus?
|
|
39
|
+
|
|
40
|
+
classes.join(' ')
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def wrapper_dom_id
|
|
44
|
+
@wrapper_dom_id ||= "#{dom_id.to_s.gsub((association_primary_key || method).to_s, sanitized_method_name.to_s)}_input"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
module Inputs
|
|
3
|
+
# Boolean inputs are used to render an input for a single checkbox, typically for attributes
|
|
4
|
+
# with a simple yes/no or true/false value. Boolean inputs are used by default for boolean
|
|
5
|
+
# database columns.
|
|
6
|
+
#
|
|
7
|
+
# @example Full form context and markup
|
|
8
|
+
# <%= semantic_form_for @post %>
|
|
9
|
+
# <%= f.inputs do %>
|
|
10
|
+
# <%= f.input :published, :as => :boolean %>
|
|
11
|
+
# <% end %>
|
|
12
|
+
# <% end %>
|
|
13
|
+
#
|
|
14
|
+
# <form...>
|
|
15
|
+
# <fieldset>
|
|
16
|
+
# <ol>
|
|
17
|
+
# <li class="boolean" id="post_published_input">
|
|
18
|
+
# <input type="hidden" name="post[published]" id="post_published" value="0">
|
|
19
|
+
# <label for="post_published">
|
|
20
|
+
# <input type="checkbox" name="post[published]" id="post_published" value="1">
|
|
21
|
+
# Published?
|
|
22
|
+
# </label>
|
|
23
|
+
# </li>
|
|
24
|
+
# </ol>
|
|
25
|
+
# </fieldset>
|
|
26
|
+
# </form>
|
|
27
|
+
#
|
|
28
|
+
# @example Set the values for the checked and unchecked states
|
|
29
|
+
# <%= f.input :published, :checked_value => "yes", :unchecked_value => "no" %>
|
|
30
|
+
#
|
|
31
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
|
32
|
+
class BooleanInput
|
|
33
|
+
include Base
|
|
34
|
+
|
|
35
|
+
def to_html
|
|
36
|
+
input_wrapping do
|
|
37
|
+
hidden_field_html <<
|
|
38
|
+
label_with_nested_checkbox
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def hidden_field_html
|
|
43
|
+
template.hidden_field_tag(input_html_options[:name], unchecked_value, :id => nil, :disabled => input_html_options[:disabled] )
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def label_with_nested_checkbox
|
|
47
|
+
builder.label(
|
|
48
|
+
method,
|
|
49
|
+
label_text_with_embedded_checkbox,
|
|
50
|
+
label_html_options
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def label_html_options
|
|
55
|
+
{
|
|
56
|
+
:for => input_html_options[:id],
|
|
57
|
+
:class => super[:class] - ['label'] # remove 'label' class
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def label_text_with_embedded_checkbox
|
|
62
|
+
check_box_html << "" << label_text
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def check_box_html
|
|
66
|
+
template.check_box_tag("#{object_name}[#{method}]", checked_value, checked?, input_html_options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def unchecked_value
|
|
70
|
+
options[:unchecked_value] || '0'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def checked_value
|
|
74
|
+
options[:checked_value] || '1'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def responds_to_global_required?
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def input_html_options
|
|
82
|
+
{:name => input_html_options_name}.merge(super)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def input_html_options_name
|
|
86
|
+
if builder.options.key?(:index)
|
|
87
|
+
"#{object_name}[#{builder.options[:index]}][#{method}]"
|
|
88
|
+
else
|
|
89
|
+
"#{object_name}[#{method}]"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def checked?
|
|
94
|
+
object && boolean_checked?(object.send(method), checked_value)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def boolean_checked?(value, checked_value)
|
|
100
|
+
case value
|
|
101
|
+
when TrueClass, FalseClass
|
|
102
|
+
value
|
|
103
|
+
when NilClass
|
|
104
|
+
false
|
|
105
|
+
when Integer
|
|
106
|
+
value == checked_value.to_i
|
|
107
|
+
when String
|
|
108
|
+
value == checked_value
|
|
109
|
+
when Array
|
|
110
|
+
value.include?(checked_value)
|
|
111
|
+
else
|
|
112
|
+
value.to_i != 0
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
module Inputs
|
|
3
|
+
|
|
4
|
+
# A CheckBoxes input is used to render a series of checkboxes. This is an alternative input choice
|
|
5
|
+
# for `has_many` or `has_and_belongs_to_many` associations like a `Post` belonging to many
|
|
6
|
+
# `categories` (by default, a {SelectInput `:select`} input is used, allowing multiple selections).
|
|
7
|
+
#
|
|
8
|
+
# Within the standard `<li>` wrapper, the output is a `<fieldset>` with a `<legend>` to
|
|
9
|
+
# represent the "label" for the input, and an `<ol>` containing `<li>`s for each choice in
|
|
10
|
+
# the association. Each `<li>` choice contains a hidden `<input>` tag for the "unchecked"
|
|
11
|
+
# value (like Rails), and a `<label>` containing the checkbox `<input>` and the label text
|
|
12
|
+
# for each choice.
|
|
13
|
+
#
|
|
14
|
+
# @example Basic example with full form context
|
|
15
|
+
#
|
|
16
|
+
# <%= semantic_form_for @post do |f| %>
|
|
17
|
+
# <%= f.inputs do %>
|
|
18
|
+
# <%= f.input :categories, :as => :check_boxes %>
|
|
19
|
+
# <% end %>
|
|
20
|
+
# <% end %>
|
|
21
|
+
#
|
|
22
|
+
# <li class='check_boxes'>
|
|
23
|
+
# <fieldset>
|
|
24
|
+
# <legend class="label"><label>Categories</label></legend>
|
|
25
|
+
# <ol>
|
|
26
|
+
# <li>
|
|
27
|
+
# <input type="hidden" name="post[category_ids][1]" value="">
|
|
28
|
+
# <label for="post_category_ids_1"><input id="post_category_ids_1" name="post[category_ids][1]" type="checkbox" value="1" /> Ruby</label>
|
|
29
|
+
# </li>
|
|
30
|
+
# <li>
|
|
31
|
+
# <input type="hidden" name="post[category_ids][2]" value="">
|
|
32
|
+
# <label for="post_category_ids_2"><input id="post_category_ids_2" name="post[category_ids][2]" type="checkbox" value="2" /> Rails</label>
|
|
33
|
+
# </li>
|
|
34
|
+
# </ol>
|
|
35
|
+
# </fieldset>
|
|
36
|
+
# </li>
|
|
37
|
+
#
|
|
38
|
+
# @example `:collection` can be used to customize the choices
|
|
39
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => @categories %>
|
|
40
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => Category.all %>
|
|
41
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => Category.some_named_scope %>
|
|
42
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => Category.pluck(:label, :id) %>
|
|
43
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [Category.find_by_name("Ruby"), Category.find_by_name("Rails")] %>
|
|
44
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => ["Ruby", "Rails"] %>
|
|
45
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", "ruby"], ["Rails", "rails"]] %>
|
|
46
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", "1"], ["Rails", "2"]] %>
|
|
47
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1], ["Rails", 2]] %>
|
|
48
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", 1, {'data-attr' => 'attr-value'}]] %>
|
|
49
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => 1..5 %>
|
|
50
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [:ruby, :rails] %>
|
|
51
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => [["Ruby", :ruby], ["Rails", :rails]] %>
|
|
52
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => Set.new([:ruby, :rails]) %>
|
|
53
|
+
#
|
|
54
|
+
# @example `:hidden_fields` can be used to skip Rails' rendering of a hidden field before every checkbox
|
|
55
|
+
# <%= f.input :categories, :as => :check_boxes, :hidden_fields => false %>
|
|
56
|
+
#
|
|
57
|
+
# @example `:disabled` can be used to disable any checkboxes with a value found in the given Array
|
|
58
|
+
# <%= f.input :categories, :as => :check_boxes, :collection => ["a", "b"], :disabled => ["a"] %>
|
|
59
|
+
#
|
|
60
|
+
# @example `:value_as_class` can be used to add a class to the `<li>` wrapped around each choice using the checkbox value for custom styling of each choice
|
|
61
|
+
# <%= f.input :categories, :as => :check_boxes, :value_as_class => true %>
|
|
62
|
+
#
|
|
63
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
|
64
|
+
# @see Formtastic::Inputs::BooleanInput BooleanInput for a single checkbox for boolean (checked = true) inputs
|
|
65
|
+
#
|
|
66
|
+
# @todo Do/can we support the per-item HTML options like RadioInput?
|
|
67
|
+
class CheckBoxesInput
|
|
68
|
+
include Base
|
|
69
|
+
include Base::Collections
|
|
70
|
+
include Base::Choices
|
|
71
|
+
|
|
72
|
+
def initialize(*args)
|
|
73
|
+
super
|
|
74
|
+
raise Formtastic::UnsupportedEnumCollection if collection_from_enum?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_html
|
|
78
|
+
input_wrapping do
|
|
79
|
+
choices_wrapping do
|
|
80
|
+
legend_html <<
|
|
81
|
+
hidden_field_for_all <<
|
|
82
|
+
choices_group_wrapping do
|
|
83
|
+
collection.map { |choice|
|
|
84
|
+
choice_wrapping(choice_wrapping_html_options(choice)) do
|
|
85
|
+
choice_html(choice)
|
|
86
|
+
end
|
|
87
|
+
}.join("\n").html_safe
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def choice_html(choice)
|
|
94
|
+
template.content_tag(
|
|
95
|
+
:label,
|
|
96
|
+
checkbox_input(choice) + choice_label(choice),
|
|
97
|
+
label_html_options.merge(:for => choice_input_dom_id(choice), :class => nil)
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def hidden_field_for_all
|
|
102
|
+
if hidden_fields?
|
|
103
|
+
''
|
|
104
|
+
else
|
|
105
|
+
options = {}
|
|
106
|
+
options[:class] = [method.to_s.singularize, 'default'].join('_') if value_as_class?
|
|
107
|
+
options[:id] = [object_name, method, 'none'].join('_')
|
|
108
|
+
template.hidden_field_tag(input_name, '', options)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def hidden_fields?
|
|
113
|
+
options[:hidden_fields]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def check_box_with_hidden_input(choice)
|
|
117
|
+
value = choice_value(choice)
|
|
118
|
+
builder.check_box(
|
|
119
|
+
association_primary_key || method,
|
|
120
|
+
extra_html_options(choice).merge(:id => choice_input_dom_id(choice), :name => input_name, :disabled => disabled?(value), :required => false),
|
|
121
|
+
value,
|
|
122
|
+
unchecked_value
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def check_box_without_hidden_input(choice)
|
|
127
|
+
value = choice_value(choice)
|
|
128
|
+
template.check_box_tag(
|
|
129
|
+
input_name,
|
|
130
|
+
value,
|
|
131
|
+
checked?(value),
|
|
132
|
+
extra_html_options(choice).merge(:id => choice_input_dom_id(choice), :disabled => disabled?(value), :required => false)
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def extra_html_options(choice)
|
|
137
|
+
input_html_options.merge(custom_choice_html_options(choice))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def checked?(value)
|
|
141
|
+
selected_values.include?(value)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def disabled?(value)
|
|
145
|
+
disabled_values.include?(value)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def selected_values
|
|
149
|
+
@selected_values ||= make_selected_values
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def disabled_values
|
|
153
|
+
vals = options[:disabled] || []
|
|
154
|
+
vals = [vals] unless vals.is_a?(Array)
|
|
155
|
+
vals
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def unchecked_value
|
|
159
|
+
options[:unchecked_value] || ''
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def input_name
|
|
163
|
+
if builder.options.key?(:index)
|
|
164
|
+
"#{object_name}[#{builder.options[:index]}][#{association_primary_key || method}][]"
|
|
165
|
+
else
|
|
166
|
+
"#{object_name}[#{association_primary_key || method}][]"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
protected
|
|
171
|
+
|
|
172
|
+
def checkbox_input(choice)
|
|
173
|
+
if hidden_fields?
|
|
174
|
+
check_box_with_hidden_input(choice)
|
|
175
|
+
else
|
|
176
|
+
check_box_without_hidden_input(choice)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def make_selected_values
|
|
181
|
+
if object.respond_to?(method)
|
|
182
|
+
selected_items = object.send(method)
|
|
183
|
+
# Construct an array from the return value, regardless of the return type
|
|
184
|
+
selected_items = [*selected_items].compact.flatten
|
|
185
|
+
|
|
186
|
+
selected = []
|
|
187
|
+
selected_items.map do |selected_item|
|
|
188
|
+
selected_item_id = selected_item.id if selected_item.respond_to? :id
|
|
189
|
+
item = send_or_call_or_object(value_method, selected_item) || selected_item_id
|
|
190
|
+
end.compact
|
|
191
|
+
else
|
|
192
|
+
[]
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
module Inputs
|
|
3
|
+
|
|
4
|
+
# Outputs a simple `<label>` with a HTML5 `<input type="color">` wrapped in the standard
|
|
5
|
+
# `<li>` wrapper. This is the default input choice for attributes with a name matching
|
|
6
|
+
# `/color/`, but can be applied to any text-like input with `:as => :color`.
|
|
7
|
+
#
|
|
8
|
+
# @example Full form context and output
|
|
9
|
+
#
|
|
10
|
+
# <%= semantic_form_for(@user) do |f| %>
|
|
11
|
+
# <%= f.inputs do %>
|
|
12
|
+
# <%= f.input :color, :as => :color %>
|
|
13
|
+
# <% end %>
|
|
14
|
+
# <% end %>
|
|
15
|
+
#
|
|
16
|
+
# <form...>
|
|
17
|
+
# <fieldset>
|
|
18
|
+
# <ol>
|
|
19
|
+
# <li class="color">
|
|
20
|
+
# <label for="user_color">Color</label>
|
|
21
|
+
# <input type="color" id="user_color" name="user[color]">
|
|
22
|
+
# </li>
|
|
23
|
+
# </ol>
|
|
24
|
+
# </fieldset>
|
|
25
|
+
# </form>
|
|
26
|
+
#
|
|
27
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
|
28
|
+
class ColorInput
|
|
29
|
+
include Base
|
|
30
|
+
include Base::Stringish
|
|
31
|
+
include Base::Placeholder
|
|
32
|
+
|
|
33
|
+
def to_html
|
|
34
|
+
raise "The :color input requires the color_field form helper, which is only available in Rails 4+" unless builder.respond_to?(:color_field)
|
|
35
|
+
input_wrapping do
|
|
36
|
+
label_html <<
|
|
37
|
+
builder.color_field(method, input_html_options)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module Formtastic
|
|
2
|
+
module Inputs
|
|
3
|
+
# Outputs a country select input, wrapping around a regular country_select helper.
|
|
4
|
+
# Rails doesn't come with a `country_select` helper by default any more, so you'll need to do
|
|
5
|
+
# one of the following:
|
|
6
|
+
#
|
|
7
|
+
# * install the [country_select](https://github.com/stefanpenner/country_select) gem
|
|
8
|
+
# * install any other country_select plugin that behaves in a similar way
|
|
9
|
+
# * roll your own `country_select` helper with the same args and options as the Rails one
|
|
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
|
+
#
|
|
14
|
+
# By default, Formtastic includes a handful of English-speaking countries as "priority
|
|
15
|
+
# countries", which can be set in the `priority_countries` configuration array in the
|
|
16
|
+
# formtastic.rb initializer to suit your market and user base (see README for more info on
|
|
17
|
+
# configuration). Additionally, it is possible to set the :priority_countries on a per-input
|
|
18
|
+
# basis through the `:priority_countries` option. These priority countries will be passed down
|
|
19
|
+
# to the `country_select` helper of your choice, and may or may not be used by the helper.
|
|
20
|
+
#
|
|
21
|
+
# @example Basic example with full form context using `priority_countries` from config
|
|
22
|
+
#
|
|
23
|
+
# <%= semantic_form_for @user do |f| %>
|
|
24
|
+
# <%= f.inputs do %>
|
|
25
|
+
# <%= f.input :nationality, :as => :country %>
|
|
26
|
+
# <% end %>
|
|
27
|
+
# <% end %>
|
|
28
|
+
#
|
|
29
|
+
# <li class='country'>
|
|
30
|
+
# <label for="user_nationality">Country</label>
|
|
31
|
+
# <select id="user_nationality" name="user[nationality]">
|
|
32
|
+
# <option value="...">...</option>
|
|
33
|
+
# # ...
|
|
34
|
+
# </li>
|
|
35
|
+
#
|
|
36
|
+
# @example `:priority_countries` set on a specific input (country_select 1.x)
|
|
37
|
+
#
|
|
38
|
+
# <%= semantic_form_for @user do |f| %>
|
|
39
|
+
# <%= f.inputs do %>
|
|
40
|
+
# <%= f.input :nationality, :as => :country, :priority_countries => ["Australia", "New Zealand"] %>
|
|
41
|
+
# <% end %>
|
|
42
|
+
# <% end %>
|
|
43
|
+
#
|
|
44
|
+
# <li class='country'>
|
|
45
|
+
# <label for="user_nationality">Country</label>
|
|
46
|
+
# <select id="user_nationality" name="user[nationality]">
|
|
47
|
+
# <option value="...">...</option>
|
|
48
|
+
# # ...
|
|
49
|
+
# </li>
|
|
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
|
+
#
|
|
66
|
+
# @see Formtastic::Helpers::InputsHelper#input InputsHelper#input for full documentation of all possible options.
|
|
67
|
+
class CountryInput
|
|
68
|
+
include Base
|
|
69
|
+
|
|
70
|
+
CountrySelectPluginMissing = Class.new(StandardError)
|
|
71
|
+
|
|
72
|
+
def to_html
|
|
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)
|
|
74
|
+
input_wrapping do
|
|
75
|
+
label_html <<
|
|
76
|
+
builder.country_select(method, priority_countries, input_options, input_html_options)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def priority_countries
|
|
81
|
+
options[:priority_countries] || builder.priority_countries
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|