padrino-helpers 0.11.3 → 0.11.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +1 -1
- data/lib/padrino-helpers.rb +3 -5
- data/lib/padrino-helpers/asset_tag_helpers.rb +32 -40
- data/lib/padrino-helpers/breadcrumb_helpers.rb +21 -39
- data/lib/padrino-helpers/form_builder/abstract_form_builder.rb +121 -118
- data/lib/padrino-helpers/form_builder/standard_form_builder.rb +6 -9
- data/lib/padrino-helpers/form_helpers.rb +190 -193
- data/lib/padrino-helpers/format_helpers.rb +29 -42
- data/lib/padrino-helpers/locale/cs.yml +14 -14
- data/lib/padrino-helpers/locale/da.yml +1 -1
- data/lib/padrino-helpers/locale/de.yml +1 -1
- data/lib/padrino-helpers/locale/en.yml +16 -16
- data/lib/padrino-helpers/locale/es.yml +16 -16
- data/lib/padrino-helpers/locale/fr.yml +1 -2
- data/lib/padrino-helpers/locale/hu.yml +16 -16
- data/lib/padrino-helpers/locale/it.yml +2 -2
- data/lib/padrino-helpers/locale/ja.yml +16 -16
- data/lib/padrino-helpers/locale/lv.yml +16 -16
- data/lib/padrino-helpers/locale/nl.yml +1 -1
- data/lib/padrino-helpers/locale/no.yml +1 -1
- data/lib/padrino-helpers/locale/pl.yml +7 -7
- data/lib/padrino-helpers/locale/pt_br.yml +16 -16
- data/lib/padrino-helpers/locale/ro.yml +16 -16
- data/lib/padrino-helpers/locale/ru.yml +16 -16
- data/lib/padrino-helpers/locale/sv.yml +16 -16
- data/lib/padrino-helpers/locale/tr.yml +16 -16
- data/lib/padrino-helpers/locale/uk.yml +16 -16
- data/lib/padrino-helpers/locale/zh_cn.yml +16 -16
- data/lib/padrino-helpers/locale/zh_tw.yml +16 -16
- data/lib/padrino-helpers/number_helpers.rb +10 -15
- data/lib/padrino-helpers/output_helpers.rb +49 -57
- data/lib/padrino-helpers/output_helpers/abstract_handler.rb +16 -18
- data/lib/padrino-helpers/output_helpers/erb_handler.rb +11 -12
- data/lib/padrino-helpers/output_helpers/haml_handler.rb +9 -9
- data/lib/padrino-helpers/output_helpers/slim_handler.rb +11 -13
- data/lib/padrino-helpers/render_helpers.rb +5 -6
- data/lib/padrino-helpers/tag_helpers.rb +18 -21
- data/lib/padrino-helpers/translation_helpers.rb +4 -6
- data/test/fixtures/markup_app/app.rb +7 -3
- data/test/fixtures/render_app/app.rb +1 -0
- data/test/test_asset_tag_helpers.rb +1 -1
- data/test/test_form_builder.rb +5 -6
- data/test/test_form_helpers.rb +24 -12
- data/test/test_format_helpers.rb +3 -3
- data/test/test_number_helpers.rb +4 -0
- data/test/test_output_helpers.rb +1 -1
- data/test/test_render_helpers.rb +1 -1
- data/test/test_tag_helpers.rb +1 -1
- metadata +9 -15
@@ -1,7 +1,7 @@
|
|
1
1
|
module Padrino
|
2
2
|
module Helpers
|
3
|
-
module FormBuilder
|
4
|
-
class AbstractFormBuilder
|
3
|
+
module FormBuilder
|
4
|
+
class AbstractFormBuilder
|
5
5
|
attr_accessor :template, :object, :multipart
|
6
6
|
|
7
7
|
def initialize(template, object, options={})
|
@@ -12,37 +12,32 @@ module Padrino
|
|
12
12
|
raise "FormBuilder object must not be a nil value. If there's no object, use a symbol instead! (i.e :user)" unless object
|
13
13
|
end
|
14
14
|
|
15
|
-
# f.error_messages
|
16
15
|
def error_messages(*params)
|
17
16
|
params.unshift object
|
18
17
|
@template.error_messages_for(*params)
|
19
18
|
end
|
20
19
|
|
21
|
-
# f.error_message_on(field)
|
22
20
|
def error_message_on(field, options={})
|
23
21
|
@template.error_message_on(object, field, options)
|
24
22
|
end
|
25
23
|
|
26
|
-
# f.label :username, :caption => "Nickname"
|
27
24
|
def label(field, options={}, &block)
|
28
25
|
options.reverse_merge!(:caption => "#{field_human_name(field)}: ")
|
29
26
|
@template.label_tag(field_id(field), options, &block)
|
30
27
|
end
|
31
28
|
|
32
|
-
# f.hidden_field :session_id, :value => "45"
|
33
29
|
def hidden_field(field, options={})
|
34
30
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
35
31
|
@template.hidden_field_tag field_name(field), options
|
36
32
|
end
|
37
33
|
|
38
|
-
# f.text_field :username, :value => "(blank)", :id => 'username'
|
39
34
|
def text_field(field, options={})
|
40
35
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
41
36
|
options.merge!(:class => field_error(field, options))
|
42
37
|
@template.text_field_tag field_name(field), options
|
43
38
|
end
|
44
39
|
|
45
|
-
|
40
|
+
def number_field(field, options={})
|
46
41
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
47
42
|
options.merge!(:class => field_error(field, options))
|
48
43
|
@template.number_field_tag field_name(field), options
|
@@ -73,35 +68,28 @@ module Padrino
|
|
73
68
|
@template.url_field_tag field_name(field), options
|
74
69
|
end
|
75
70
|
|
76
|
-
# f.text_area :summary, :value => "(enter summary)", :id => 'summary'
|
77
71
|
def text_area(field, options={})
|
78
72
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
79
73
|
options.merge!(:class => field_error(field, options))
|
80
74
|
@template.text_area_tag field_name(field), options
|
81
75
|
end
|
82
76
|
|
83
|
-
# f.password_field :password, :id => 'password'
|
84
77
|
def password_field(field, options={})
|
85
78
|
options.reverse_merge!(:value => field_value(field), :id => field_id(field))
|
86
79
|
options.merge!(:class => field_error(field, options))
|
87
80
|
@template.password_field_tag field_name(field), options
|
88
81
|
end
|
89
82
|
|
90
|
-
# f.select :color, :options => ['red', 'green'], :include_blank => true
|
91
|
-
# f.select :color, :collection => @colors, :fields => [:name, :id]
|
92
83
|
def select(field, options={})
|
93
84
|
options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
|
94
85
|
options.merge!(:class => field_error(field, options))
|
95
86
|
@template.select_tag field_name(field), options
|
96
87
|
end
|
97
88
|
|
98
|
-
# f.check_box_group :color, :options => ['red', 'green', 'blue'], :selected => ['red', 'blue']
|
99
|
-
# f.check_box_group :color, :collection => @colors, :fields => [:name, :id]
|
100
89
|
def check_box_group(field, options={})
|
101
90
|
selected_values = Array(options[:selected] || field_value(field))
|
102
91
|
if options[:collection]
|
103
92
|
fields = options[:fields] || [:name, :id]
|
104
|
-
# don't use map!, it will break some orms
|
105
93
|
selected_values = selected_values.map{ |v| (v.respond_to?(fields[0]) ? v.send(fields[1]) : v).to_s }
|
106
94
|
end
|
107
95
|
labeled_group( field, options ) do |variant|
|
@@ -109,8 +97,6 @@ module Padrino
|
|
109
97
|
end
|
110
98
|
end
|
111
99
|
|
112
|
-
# f.radio_button_group :color, :options => ['red', 'green']
|
113
|
-
# f.radio_button_group :color, :collection => @colors, :fields => [:name, :id], :selected => @colors.first
|
114
100
|
def radio_button_group(field, options={})
|
115
101
|
fields = options[:fields] || [:name, :id]
|
116
102
|
selected_value = options[:selected] || field_value(field)
|
@@ -120,7 +106,6 @@ module Padrino
|
|
120
106
|
end
|
121
107
|
end
|
122
108
|
|
123
|
-
# f.check_box :remember_me, :value => 'true', :uncheck_value => '0'
|
124
109
|
def check_box(field, options={})
|
125
110
|
html = ActiveSupport::SafeBuffer.new
|
126
111
|
unchecked_value = options.delete(:uncheck_value) || '0'
|
@@ -130,14 +115,12 @@ module Padrino
|
|
130
115
|
html << @template.check_box_tag(field_name(field), options)
|
131
116
|
end
|
132
117
|
|
133
|
-
# f.radio_button :gender, :value => 'male'
|
134
118
|
def radio_button(field, options={})
|
135
119
|
options.reverse_merge!(:id => field_id(field, options[:value]))
|
136
120
|
options.reverse_merge!(:checked => true) if values_matches_field?(field, options[:value])
|
137
121
|
@template.radio_button_tag field_name(field), options
|
138
122
|
end
|
139
123
|
|
140
|
-
# f.file_field :photo, :class => 'avatar'
|
141
124
|
def file_field(field, options={})
|
142
125
|
self.multipart = true
|
143
126
|
options.reverse_merge!(:id => field_id(field))
|
@@ -145,19 +128,18 @@ module Padrino
|
|
145
128
|
@template.file_field_tag field_name(field), options
|
146
129
|
end
|
147
130
|
|
148
|
-
# f.submit "Update", :class => 'large'
|
149
131
|
def submit(*args)
|
150
132
|
options = args[-1].is_a?(Hash) ? args.pop : {}
|
151
133
|
caption = args.length >= 1 ? args.shift : "Submit"
|
152
134
|
@template.submit_tag caption, options
|
153
135
|
end
|
154
136
|
|
155
|
-
# f.image_submit "buttons/submit.png", :class => 'large'
|
156
137
|
def image_submit(source, options={})
|
157
138
|
@template.image_submit_tag source, options
|
158
139
|
end
|
159
140
|
|
160
|
-
|
141
|
+
##
|
142
|
+
# Supports nested fields for a child model within a form.
|
161
143
|
# f.fields_for :addresses
|
162
144
|
# f.fields_for :addresses, address
|
163
145
|
# f.fields_for :addresses, @addresses
|
@@ -166,7 +148,7 @@ module Padrino
|
|
166
148
|
include_index = default_collection.respond_to?(:each)
|
167
149
|
nested_options = { :parent => self, :association => child_association }
|
168
150
|
nested_objects = instance_or_collection ? Array(instance_or_collection) : Array(default_collection)
|
169
|
-
|
151
|
+
nested_objects.each_with_index.map do |child_instance, index|
|
170
152
|
nested_options[:index] = include_index ? index : nil
|
171
153
|
@template.fields_for(child_instance, { :nested => nested_options }, &block)
|
172
154
|
end.join("\n").html_safe
|
@@ -177,112 +159,133 @@ module Padrino
|
|
177
159
|
end
|
178
160
|
|
179
161
|
protected
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
162
|
+
# Returns the known field types for a Formbuilder.
|
163
|
+
def self.field_types
|
164
|
+
[:hidden_field, :text_field, :text_area, :password_field, :file_field, :radio_button, :check_box, :select]
|
165
|
+
end
|
184
166
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
167
|
+
##
|
168
|
+
# Returns true if the value matches the value in the field.
|
169
|
+
# field_has_value?(:gender, 'male')
|
170
|
+
def values_matches_field?(field, value)
|
171
|
+
value.present? && (field_value(field).to_s == value.to_s || field_value(field).to_s == 'true')
|
172
|
+
end
|
190
173
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
174
|
+
##
|
175
|
+
# Add a :invalid css class to the field if it contain an error.
|
176
|
+
#
|
177
|
+
def field_error(field, options)
|
178
|
+
error = @object.errors[field] rescue nil
|
179
|
+
error.blank? ? options[:class] : [options[:class], :invalid].flatten.compact.join(" ")
|
180
|
+
end
|
196
181
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
182
|
+
##
|
183
|
+
# Returns the human name of the field. Look that use builtin I18n.
|
184
|
+
#
|
185
|
+
def field_human_name(field)
|
186
|
+
I18n.translate("#{object_model_name}.attributes.#{field}", :count => 1, :default => field.to_s.humanize, :scope => :models)
|
187
|
+
end
|
201
188
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
189
|
+
##
|
190
|
+
# Returns the name for the given field.
|
191
|
+
# field_name(:username) => "user[username]"
|
192
|
+
# field_name(:number) => "user[telephone_attributes][number]"
|
193
|
+
# field_name(:street) => "user[addresses_attributes][0][street]"
|
194
|
+
def field_name(field=nil)
|
195
|
+
result = field_result
|
196
|
+
result << field_name_fragment if nested_form?
|
197
|
+
result << "[#{field}]" unless field.blank?
|
198
|
+
result.flatten.join
|
199
|
+
end
|
212
200
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
201
|
+
##
|
202
|
+
# Returns the id for the given field.
|
203
|
+
# field_id(:username) => "user_username"
|
204
|
+
# field_id(:gender, :male) => "user_gender_male"
|
205
|
+
# field_name(:number) => "user_telephone_attributes_number"
|
206
|
+
# field_name(:street) => "user_addresses_attributes_0_street"
|
207
|
+
def field_id(field=nil, value=nil)
|
208
|
+
result = []
|
209
|
+
result << "#{@options[:namespace]}_" if @options[:namespace] && root_form?
|
210
|
+
result << field_result
|
211
|
+
result << field_id_fragment if nested_form?
|
212
|
+
result << "_#{field}" unless field.blank?
|
213
|
+
result << "_#{value}" unless value.blank?
|
214
|
+
result.flatten.join
|
215
|
+
end
|
227
216
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
217
|
+
##
|
218
|
+
# Returns the child object if it exists.
|
219
|
+
#
|
220
|
+
def nested_object_id
|
221
|
+
nested_form? && object.respond_to?(:new_record?) && !object.new_record? && object.id
|
222
|
+
end
|
232
223
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
224
|
+
##
|
225
|
+
# Returns true if this form object is nested in a parent form.
|
226
|
+
#
|
227
|
+
def nested_form?
|
228
|
+
@options[:nested] && @options[:nested][:parent] && @options[:nested][:parent].respond_to?(:object)
|
229
|
+
end
|
237
230
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
231
|
+
##
|
232
|
+
# Returns the value for the object's field.
|
233
|
+
#
|
234
|
+
def field_value(field)
|
235
|
+
@object && @object.respond_to?(field) ? @object.send(field) : ""
|
236
|
+
end
|
243
237
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
238
|
+
##
|
239
|
+
# Returns a new record of the type specified in the object
|
240
|
+
#
|
241
|
+
def build_object(object_or_symbol)
|
242
|
+
object_or_symbol.is_a?(Symbol) ? @template.instance_variable_get("@#{object_or_symbol}") || object_class(object_or_symbol).new : object_or_symbol
|
243
|
+
end
|
249
244
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
245
|
+
##
|
246
|
+
# Returns the object's models name.
|
247
|
+
#
|
248
|
+
def object_model_name(explicit_object=object)
|
249
|
+
explicit_object.is_a?(Symbol) ? explicit_object : explicit_object.class.to_s.underscore.gsub(/\//, '_')
|
250
|
+
end
|
255
251
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
252
|
+
##
|
253
|
+
# Returns the class type for the given object.
|
254
|
+
#
|
255
|
+
def object_class(explicit_object)
|
256
|
+
explicit_object.is_a?(Symbol) ? explicit_object.to_s.camelize.constantize : explicit_object.class
|
257
|
+
end
|
260
258
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
259
|
+
##
|
260
|
+
# Returns true if this form is the top-level (not nested).
|
261
|
+
#
|
262
|
+
def root_form?
|
263
|
+
!nested_form?
|
264
|
+
end
|
265
265
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
266
|
+
##
|
267
|
+
# Builds a group of labels for radios or checkboxes.
|
268
|
+
#
|
269
|
+
def labeled_group(field, options={})
|
270
|
+
options.reverse_merge!(:id => field_id(field), :selected => field_value(field))
|
271
|
+
options.merge!(:class => field_error(field, options))
|
272
|
+
variants = case
|
273
|
+
when options[:options]
|
274
|
+
options[:options].map{ |caption, value| [caption.to_s, (value||caption).to_s] }
|
275
|
+
when options[:collection]
|
276
|
+
fields = options[:fields] || [:name, :id]
|
277
|
+
options[:collection].map{ |variant| [variant.send(fields.first).to_s, variant.send(fields.last).to_s] }
|
278
|
+
else
|
279
|
+
[]
|
280
|
+
end
|
281
|
+
variants.inject(''.html_safe) do |html, variant|
|
282
|
+
variant[2] = "#{field_id(field)}_#{variant[1]}"
|
283
|
+
html << @template.label_tag("#{field_name(field)}[]", :for => variant[2], :caption => "#{yield(variant)} #{variant[0]}")
|
283
284
|
end
|
285
|
+
end
|
284
286
|
|
285
287
|
private
|
288
|
+
|
286
289
|
def field_result
|
287
290
|
result = []
|
288
291
|
result << object_model_name if root_form?
|
@@ -308,7 +311,7 @@ module Padrino
|
|
308
311
|
:attributes_name => "#{@options[:nested][:association]}_attributes"
|
309
312
|
}
|
310
313
|
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
@@ -2,9 +2,8 @@ require File.expand_path(File.dirname(__FILE__) + '/abstract_form_builder') unle
|
|
2
2
|
|
3
3
|
module Padrino
|
4
4
|
module Helpers
|
5
|
-
module FormBuilder
|
6
|
-
class StandardFormBuilder < AbstractFormBuilder
|
7
|
-
|
5
|
+
module FormBuilder
|
6
|
+
class StandardFormBuilder < AbstractFormBuilder
|
8
7
|
##
|
9
8
|
# StandardFormBuilder
|
10
9
|
#
|
@@ -26,18 +25,16 @@ module Padrino
|
|
26
25
|
EOF
|
27
26
|
end
|
28
27
|
|
29
|
-
# submit_block("Update")
|
30
28
|
def submit_block(caption, options={})
|
31
29
|
submit_html = self.submit(caption, options)
|
32
30
|
@template.content_tag(:p, submit_html)
|
33
31
|
end
|
34
32
|
|
35
|
-
# image_submit_block("submit.png")
|
36
33
|
def image_submit_block(source, options={})
|
37
34
|
submit_html = self.image_submit(source, options)
|
38
35
|
@template.content_tag(:p, submit_html)
|
39
36
|
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -7,16 +7,16 @@ module Padrino
|
|
7
7
|
#
|
8
8
|
module FormHelpers
|
9
9
|
##
|
10
|
-
# Constructs a form for object using given or default form_builder
|
10
|
+
# Constructs a form for object using given or default form_builder.
|
11
11
|
#
|
12
12
|
# @param [Object] object
|
13
13
|
# The object for which the form is being built.
|
14
|
-
# @param [String]
|
14
|
+
# @param [String] URL
|
15
15
|
# The url this form will submit to.
|
16
16
|
# @param [Hash] settings
|
17
17
|
# The settings associated with this form.
|
18
18
|
# Accepts a :namespace option that will be prepended to the id attributes of the form's elements.
|
19
|
-
# Also accepts
|
19
|
+
# Also accepts HTML options.
|
20
20
|
# @option settings [String] :builder ("StandardFormBuilder")
|
21
21
|
# The FormBuilder class to use such as StandardFormBuilder.
|
22
22
|
# @param [Proc] block
|
@@ -30,7 +30,6 @@ module Padrino
|
|
30
30
|
# form_for :user, '/register' do |f| ... end
|
31
31
|
# form_for @user, '/register', :id => 'register' do |f| ... end
|
32
32
|
#
|
33
|
-
# @api public
|
34
33
|
def form_for(object, url, settings={}, &block)
|
35
34
|
instance = builder_instance(object, settings)
|
36
35
|
html = capture_html(instance, &block)
|
@@ -40,13 +39,13 @@ module Padrino
|
|
40
39
|
end
|
41
40
|
|
42
41
|
##
|
43
|
-
# Constructs form fields for an object using given or default form_builder
|
44
|
-
# Used within an existing form to allow alternate objects within one form
|
42
|
+
# Constructs form fields for an object using given or default form_builder.
|
43
|
+
# Used within an existing form to allow alternate objects within one form.
|
45
44
|
#
|
46
45
|
# @param [Object] object
|
47
46
|
# The object for which the fields are being built.
|
48
47
|
# @param [Hash] settings
|
49
|
-
# The settings associated with these fields. Accepts
|
48
|
+
# The settings associated with these fields. Accepts HTML options.
|
50
49
|
# @param [Proc] block
|
51
50
|
# The content inside this set of fields.
|
52
51
|
#
|
@@ -56,7 +55,6 @@ module Padrino
|
|
56
55
|
# fields_for @user.assignment do |assignment| ... end
|
57
56
|
# fields_for :assignment do |assigment| ... end
|
58
57
|
#
|
59
|
-
# @api public
|
60
58
|
def fields_for(object, settings={}, &block)
|
61
59
|
instance = builder_instance(object, settings)
|
62
60
|
fields_html = capture_html(instance, &block)
|
@@ -65,21 +63,20 @@ module Padrino
|
|
65
63
|
end
|
66
64
|
|
67
65
|
##
|
68
|
-
# Constructs a form without object based on options
|
66
|
+
# Constructs a form without object based on options.
|
69
67
|
#
|
70
68
|
# @param [String] url
|
71
|
-
# The
|
69
|
+
# The URL this form will submit to.
|
72
70
|
# @param [Hash] options
|
73
71
|
# The html options associated with this form.
|
74
72
|
# @param [Proc] block
|
75
73
|
# The fields and content inside this form.
|
76
74
|
#
|
77
|
-
# @return [String] The
|
75
|
+
# @return [String] The HTML form with the specified options and input fields.
|
78
76
|
#
|
79
77
|
# @example
|
80
78
|
# form_tag '/register', :class => "registration_form" do ... end
|
81
79
|
#
|
82
|
-
# @api public
|
83
80
|
def form_tag(url, options={}, &block)
|
84
81
|
desired_method = options[:method].to_s
|
85
82
|
options.delete(:method) unless desired_method =~ /get|post/i
|
@@ -99,12 +96,12 @@ module Padrino
|
|
99
96
|
end
|
100
97
|
|
101
98
|
##
|
102
|
-
# Returns the hidden method field for 'put' and 'delete' forms
|
99
|
+
# Returns the hidden method field for 'put' and 'delete' forms.
|
103
100
|
# Only 'get' and 'post' are allowed within browsers;
|
104
101
|
# 'put' and 'delete' are just specified using hidden fields with form action still 'put'.
|
105
102
|
#
|
106
103
|
# @param [String] desired_method
|
107
|
-
# The method this hidden field represents (i.e put or delete)
|
104
|
+
# The method this hidden field represents (i.e put or delete).
|
108
105
|
#
|
109
106
|
# @return [String] The hidden field representing the +desired_method+ for the form.
|
110
107
|
#
|
@@ -112,14 +109,13 @@ module Padrino
|
|
112
109
|
# # Generate: <input name="_method" value="delete" />
|
113
110
|
# hidden_form_method_field('delete')
|
114
111
|
#
|
115
|
-
# @api semipublic
|
116
112
|
def hidden_form_method_field(desired_method)
|
117
113
|
return ActiveSupport::SafeBuffer.new if desired_method.blank? || desired_method.to_s =~ /get|post/i
|
118
114
|
hidden_field_tag(:_method, :value => desired_method)
|
119
115
|
end
|
120
116
|
|
121
117
|
##
|
122
|
-
# Constructs a field_set to group fields with given options
|
118
|
+
# Constructs a field_set to group fields with given options.
|
123
119
|
#
|
124
120
|
# @overload field_set_tag(legend=nil, options={}, &block)
|
125
121
|
# @param [String] legend The legend caption for the fieldset
|
@@ -135,7 +131,6 @@ module Padrino
|
|
135
131
|
# field_set_tag(:class => "office-set") { }
|
136
132
|
# field_set_tag("Office", :class => 'office-set') { }
|
137
133
|
#
|
138
|
-
# @api public
|
139
134
|
def field_set_tag(*args, &block)
|
140
135
|
options = args.extract_options!
|
141
136
|
legend_text = args[0].is_a?(String) ? args.first : nil
|
@@ -145,13 +140,13 @@ module Padrino
|
|
145
140
|
end
|
146
141
|
|
147
142
|
##
|
148
|
-
# Constructs list
|
143
|
+
# Constructs list HTML for the errors for a given symbol.
|
149
144
|
#
|
150
145
|
# @overload error_messages_for(*objects, options = {})
|
151
146
|
# @param [Array<Object>] object Splat of objects to display errors for.
|
152
147
|
# @param [Hash] options Error message display options.
|
153
148
|
# @option options [String] :header_tag ("h2")
|
154
|
-
# Used for the header of the error div
|
149
|
+
# Used for the header of the error div.
|
155
150
|
# @option options [String] :id ("field-errors")
|
156
151
|
# The id of the error div.
|
157
152
|
# @option options [String] :class ("field-errors")
|
@@ -163,7 +158,7 @@ module Padrino
|
|
163
158
|
# The object name to use in the header, or any text that you prefer.
|
164
159
|
# If +:object_name+ is not set, the name of the first object will be used.
|
165
160
|
# @option options [String] :header_message ("X errors prohibited this object from being saved")
|
166
|
-
# The message in the header of the error div.
|
161
|
+
# The message in the header of the error div. Pass +nil+ or an empty string
|
167
162
|
# to avoid the header message altogether.
|
168
163
|
# @option options [String] :message ("There were problems with the following fields:")
|
169
164
|
# The explanation message after the header message and before
|
@@ -175,7 +170,6 @@ module Padrino
|
|
175
170
|
# @example
|
176
171
|
# error_messages_for :user
|
177
172
|
#
|
178
|
-
# @api public
|
179
173
|
def error_messages_for(*objects)
|
180
174
|
options = objects.extract_options!.symbolize_keys
|
181
175
|
objects = objects.map { |object_name|
|
@@ -194,19 +188,19 @@ module Padrino
|
|
194
188
|
end
|
195
189
|
end
|
196
190
|
|
197
|
-
options[:object_name] ||= objects.first.class
|
191
|
+
options[:object_name] ||= objects.first.class.to_s.underscore.gsub(/\//, ' ')
|
198
192
|
|
199
193
|
I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
|
200
194
|
header_message = if options.include?(:header_message)
|
201
195
|
options[:header_message]
|
202
196
|
else
|
203
|
-
object_name = options[:object_name]
|
197
|
+
object_name = options[:object_name]
|
204
198
|
object_name = I18n.t(:name, :default => object_name.humanize, :scope => [:models, object_name], :count => 1)
|
205
199
|
locale.t :header, :count => count, :model => object_name
|
206
200
|
end
|
207
201
|
message = options.include?(:message) ? options[:message] : locale.t(:body)
|
208
202
|
error_messages = objects.map { |object|
|
209
|
-
object_name = options[:object_name]
|
203
|
+
object_name = options[:object_name]
|
210
204
|
object.errors.map { |f, msg|
|
211
205
|
field = I18n.t(f, :default => f.to_s.humanize, :scope => [:models, object_name, :attributes])
|
212
206
|
content_tag(:li, "%s %s" % [field, msg])
|
@@ -226,7 +220,8 @@ module Padrino
|
|
226
220
|
end
|
227
221
|
|
228
222
|
##
|
229
|
-
# Returns a string containing the error message attached to the
|
223
|
+
# Returns a string containing the error message attached to the
|
224
|
+
# +method+ on the +object+ if one exists.
|
230
225
|
#
|
231
226
|
# @param [Object] object
|
232
227
|
# The object to display the error for.
|
@@ -262,7 +257,7 @@ module Padrino
|
|
262
257
|
I18n.t("ohm.errors.messages.#{error[0]}", :default => error[0].to_s)
|
263
258
|
else
|
264
259
|
# Array(error).first is necessary because some ORMs
|
265
|
-
# give us an array others directly a value
|
260
|
+
# give us an array others directly a value.
|
266
261
|
Array(error)[0]
|
267
262
|
end
|
268
263
|
|
@@ -277,7 +272,7 @@ module Padrino
|
|
277
272
|
end
|
278
273
|
|
279
274
|
##
|
280
|
-
# Constructs a label tag from the given options
|
275
|
+
# Constructs a label tag from the given options.
|
281
276
|
#
|
282
277
|
# @param [String] name
|
283
278
|
# The name of the field to label.
|
@@ -294,7 +289,6 @@ module Padrino
|
|
294
289
|
# label_tag :username, :class => 'long-label'
|
295
290
|
# label_tag :username, :class => 'long-label' do ... end
|
296
291
|
#
|
297
|
-
# @api public
|
298
292
|
def label_tag(name, options={}, &block)
|
299
293
|
options.reverse_merge!(:caption => "#{name.to_s.humanize}: ", :for => name)
|
300
294
|
caption_text = options.delete(:caption).html_safe
|
@@ -309,7 +303,7 @@ module Padrino
|
|
309
303
|
end
|
310
304
|
|
311
305
|
##
|
312
|
-
# Creates a text field input with the given name and options
|
306
|
+
# Creates a text field input with the given name and options.
|
313
307
|
#
|
314
308
|
# @macro [new] text_field
|
315
309
|
# @param [Symbol] name
|
@@ -338,22 +332,22 @@ module Padrino
|
|
338
332
|
# @option options [Boolean] :spellcheck
|
339
333
|
# Specifies whether or not the field should have it's spelling and grammar checked for errors.
|
340
334
|
# @option options [Boolean] :draggable
|
341
|
-
# Specifies whether or not the field is draggable. (true, false, :auto)
|
335
|
+
# Specifies whether or not the field is draggable. (true, false, :auto).
|
342
336
|
# @option options [String] :pattern
|
343
337
|
# Specifies the regular expression pattern that the field's value is checked against.
|
344
338
|
# @option options [Symbol] :autocomplete
|
345
|
-
# Specifies whether or not the field should have autocomplete enabled. (:on, :off)
|
339
|
+
# Specifies whether or not the field should have autocomplete enabled. (:on, :off).
|
346
340
|
# @option options [Boolean] :autofocus
|
347
341
|
# Specifies whether or not the field should automatically get focus when the page loads.
|
348
342
|
# @option options [Boolean] :required
|
349
|
-
# Specifies whether or not the field is required to be
|
343
|
+
# Specifies whether or not the field is required to be completed before the form is submitted.
|
350
344
|
# @option options [Boolean] :readonly
|
351
345
|
# Specifies whether or not the field is read only.
|
352
346
|
# @option options [Boolean] :disabled
|
353
347
|
# Specifies whether or not the field is disabled.
|
354
348
|
#
|
355
349
|
# @return [String]
|
356
|
-
# Generated HTML with specified +options
|
350
|
+
# Generated HTML with specified +options+.
|
357
351
|
#
|
358
352
|
# @example
|
359
353
|
# text_field_tag :first_name, :maxlength => 40, :required => true
|
@@ -365,13 +359,12 @@ module Padrino
|
|
365
359
|
# text_field_tag :username, :placeholder => 'Your Username'
|
366
360
|
# # => <input name="username" placeholder="Your Username" type="text" />
|
367
361
|
#
|
368
|
-
# @api public
|
369
362
|
def text_field_tag(name, options={})
|
370
363
|
input_tag(:text, options.reverse_merge!(:name => name))
|
371
364
|
end
|
372
365
|
|
373
366
|
##
|
374
|
-
# Creates a number field input with the given name and options
|
367
|
+
# Creates a number field input with the given name and options.
|
375
368
|
#
|
376
369
|
# @macro [new] number_field
|
377
370
|
# @param [Symbol] name
|
@@ -400,11 +393,11 @@ module Padrino
|
|
400
393
|
# @option options [Boolean] :spellcheck
|
401
394
|
# Specifies whether or not the field should have it's spelling and grammar checked for errors.
|
402
395
|
# @option options [Boolean] :draggable
|
403
|
-
# Specifies whether or not the field is draggable. (true, false, :auto)
|
396
|
+
# Specifies whether or not the field is draggable. (true, false, :auto).
|
404
397
|
# @option options [String] :pattern
|
405
398
|
# Specifies the regular expression pattern that the field's value is checked against.
|
406
399
|
# @option options [Symbol] :autocomplete
|
407
|
-
# Specifies whether or not the field should have autocomplete enabled. (:on, :off)
|
400
|
+
# Specifies whether or not the field should have autocomplete enabled. (:on, :off).
|
408
401
|
# @option options [Boolean] :autofocus
|
409
402
|
# Specifies whether or not the field should automatically get focus when the page loads.
|
410
403
|
# @option options [Boolean] :required
|
@@ -415,11 +408,11 @@ module Padrino
|
|
415
408
|
# Specifies whether or not the field is disabled.
|
416
409
|
#
|
417
410
|
# @return [String]
|
418
|
-
# Generated HTML with specified +options
|
411
|
+
# Generated HTML with specified +options+.
|
419
412
|
#
|
420
413
|
# @example
|
421
|
-
# number_field_tag :
|
422
|
-
# # => <input name="
|
414
|
+
# number_field_tag :quantity, :class => 'numeric'
|
415
|
+
# # => <input name="quantity" class="numeric" type="number" />
|
423
416
|
#
|
424
417
|
# number_field_tag :zip_code, :pattern => /[0-9]{5}/
|
425
418
|
# # => <input name="zip_code" pattern="[0-9]{5}" type="number" />
|
@@ -430,13 +423,12 @@ module Padrino
|
|
430
423
|
# number_field_tag :age, :min => 18, :max => 120, :step => 1
|
431
424
|
# # => <input name="age" min="18" max="120" step="1" type="number" />
|
432
425
|
#
|
433
|
-
# @api public
|
434
426
|
def number_field_tag(name, options={})
|
435
427
|
input_tag(:number, options.reverse_merge(:name => name))
|
436
428
|
end
|
437
429
|
|
438
430
|
##
|
439
|
-
# Creates a telephone field input with the given name and options
|
431
|
+
# Creates a telephone field input with the given name and options.
|
440
432
|
#
|
441
433
|
# @macro text_field
|
442
434
|
#
|
@@ -452,14 +444,13 @@ module Padrino
|
|
452
444
|
# # => <input name="work_phone" tabindex="2" type="tel" />
|
453
445
|
# # => <input name="home_phone" tabindex="3" type="tel" />
|
454
446
|
#
|
455
|
-
# @api public
|
456
447
|
def telephone_field_tag(name, options={})
|
457
448
|
input_tag(:tel, options.reverse_merge(:name => name))
|
458
449
|
end
|
459
450
|
alias_method :phone_field_tag, :telephone_field_tag
|
460
451
|
|
461
452
|
##
|
462
|
-
# Creates an email field input with the given name and options
|
453
|
+
# Creates an email field input with the given name and options.
|
463
454
|
#
|
464
455
|
# @macro text_field
|
465
456
|
#
|
@@ -470,13 +461,12 @@ module Padrino
|
|
470
461
|
# email_field_tag :email, :value => 'padrinorb@gmail.com', :readonly => true
|
471
462
|
# # => <input name="email" value="padrinorb@gmail.com" readonly type="email" />
|
472
463
|
#
|
473
|
-
# @api public
|
474
464
|
def email_field_tag(name, options={})
|
475
465
|
input_tag(:email, options.reverse_merge(:name => name))
|
476
466
|
end
|
477
467
|
|
478
468
|
##
|
479
|
-
# Creates a search field input with the given name and options
|
469
|
+
# Creates a search field input with the given name and options.
|
480
470
|
#
|
481
471
|
# @macro text_field
|
482
472
|
#
|
@@ -493,13 +483,12 @@ module Padrino
|
|
493
483
|
# search_field_tag :search, :autofocus => true
|
494
484
|
# # => <input name="search" autofocus type="search" />
|
495
485
|
#
|
496
|
-
# @api public
|
497
486
|
def search_field_tag(name, options={})
|
498
487
|
input_tag(:search, options.reverse_merge(:name => name))
|
499
488
|
end
|
500
489
|
|
501
490
|
##
|
502
|
-
# Creates a
|
491
|
+
# Creates a URL field input with the given name and options.
|
503
492
|
#
|
504
493
|
# @macro text_field
|
505
494
|
#
|
@@ -510,43 +499,34 @@ module Padrino
|
|
510
499
|
# url_field_tag :home_page, :class => 'string url'
|
511
500
|
# <input name="home_page" class="string url", type="url" />
|
512
501
|
#
|
513
|
-
# @api public
|
514
502
|
def url_field_tag(name, options={})
|
515
503
|
input_tag(:url, options.reverse_merge(:name => name))
|
516
504
|
end
|
517
505
|
|
518
506
|
##
|
519
|
-
# Constructs a hidden field input from the given options
|
520
|
-
#
|
521
|
-
# @macro text_field
|
507
|
+
# Constructs a hidden field input from the given options.
|
522
508
|
#
|
523
509
|
# @example
|
524
510
|
# hidden_field_tag :session_key, :value => "__secret__"
|
525
511
|
#
|
526
|
-
# @api public
|
527
512
|
def hidden_field_tag(name, options={})
|
528
513
|
options.reverse_merge!(:name => name)
|
529
514
|
input_tag(:hidden, options)
|
530
515
|
end
|
531
516
|
|
532
517
|
##
|
533
|
-
# Constructs a text area input from the given options
|
534
|
-
#
|
535
|
-
# @macro text_field
|
518
|
+
# Constructs a text area input from the given options.
|
536
519
|
#
|
537
520
|
# @example
|
538
521
|
# text_area_tag :username, :class => 'long', :value => "Demo?"
|
539
522
|
#
|
540
|
-
# @api public
|
541
523
|
def text_area_tag(name, options={})
|
542
524
|
options.reverse_merge!(:name => name, :rows => "", :cols => "")
|
543
525
|
content_tag(:textarea, options.delete(:value).to_s, options)
|
544
526
|
end
|
545
527
|
|
546
528
|
##
|
547
|
-
# Constructs a password field input from the given options
|
548
|
-
#
|
549
|
-
# @macro text_field
|
529
|
+
# Constructs a password field input from the given options.
|
550
530
|
#
|
551
531
|
# @example
|
552
532
|
# password_field_tag :password, :class => 'long'
|
@@ -558,37 +538,29 @@ module Padrino
|
|
558
538
|
end
|
559
539
|
|
560
540
|
##
|
561
|
-
# Constructs a check_box from the given options
|
562
|
-
#
|
563
|
-
# @macro text_field
|
541
|
+
# Constructs a check_box from the given options.
|
564
542
|
#
|
565
543
|
# @example
|
566
544
|
# check_box_tag :remember_me, :value => 'Yes'
|
567
545
|
#
|
568
|
-
# @api public
|
569
546
|
def check_box_tag(name, options={})
|
570
547
|
options.reverse_merge!(:name => name, :value => '1')
|
571
548
|
input_tag(:checkbox, options)
|
572
549
|
end
|
573
550
|
|
574
551
|
##
|
575
|
-
# Constructs a radio_button from the given options
|
576
|
-
#
|
577
|
-
# @macro text_field
|
552
|
+
# Constructs a radio_button from the given options.
|
578
553
|
#
|
579
554
|
# @example
|
580
555
|
# radio_button_tag :remember_me, :value => 'true'
|
581
556
|
#
|
582
|
-
# @api public
|
583
557
|
def radio_button_tag(name, options={})
|
584
558
|
options.reverse_merge!(:name => name)
|
585
559
|
input_tag(:radio, options)
|
586
560
|
end
|
587
561
|
|
588
562
|
##
|
589
|
-
# Constructs a file field input from the given options
|
590
|
-
#
|
591
|
-
# @macro text_field
|
563
|
+
# Constructs a file field input from the given options.
|
592
564
|
#
|
593
565
|
# @example
|
594
566
|
# file_field_tag :photo, :class => 'long'
|
@@ -601,7 +573,7 @@ module Padrino
|
|
601
573
|
end
|
602
574
|
|
603
575
|
##
|
604
|
-
# Constructs a select from the given options
|
576
|
+
# Constructs a select from the given options.
|
605
577
|
#
|
606
578
|
# @example
|
607
579
|
# options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
|
@@ -638,9 +610,8 @@ module Padrino
|
|
638
610
|
# @option options [Boolean] :multiple (false)
|
639
611
|
# Allow multiple options to be selected at once.
|
640
612
|
#
|
641
|
-
# @return [String] The
|
613
|
+
# @return [String] The HTML input field based on the +options+ specified.
|
642
614
|
#
|
643
|
-
# @api public
|
644
615
|
def select_tag(name, options={})
|
645
616
|
options.reverse_merge!(:name => name)
|
646
617
|
collection, fields = options.delete(:collection), options.delete(:fields)
|
@@ -657,7 +628,7 @@ module Padrino
|
|
657
628
|
end
|
658
629
|
|
659
630
|
##
|
660
|
-
# Constructs a button input from the given options
|
631
|
+
# Constructs a button input from the given options.
|
661
632
|
#
|
662
633
|
# @param [String] caption
|
663
634
|
# The caption for the button.
|
@@ -669,14 +640,13 @@ module Padrino
|
|
669
640
|
# @example
|
670
641
|
# button_tag "Cancel", :class => 'clear'
|
671
642
|
#
|
672
|
-
# @api public
|
673
643
|
def button_tag(caption, options = {})
|
674
644
|
options.reverse_merge!(:value => caption)
|
675
645
|
input_tag(:button, options)
|
676
646
|
end
|
677
647
|
|
678
648
|
##
|
679
|
-
# Constructs a submit button from the given options
|
649
|
+
# Constructs a submit button from the given options.
|
680
650
|
#
|
681
651
|
# @param [String] caption (defaults to: +Submit+)
|
682
652
|
# The caption for the submit button.
|
@@ -689,7 +659,6 @@ module Padrino
|
|
689
659
|
# submit_tag "Create", :class => 'success'
|
690
660
|
# submit_tag :class => 'btn'
|
691
661
|
#
|
692
|
-
# @api public
|
693
662
|
def submit_tag(*args)
|
694
663
|
options = args[-1].is_a?(Hash) ? args.pop : {}
|
695
664
|
caption = args.length >= 1 ? args.shift : "Submit"
|
@@ -697,7 +666,8 @@ module Padrino
|
|
697
666
|
input_tag(:submit, options)
|
698
667
|
end
|
699
668
|
|
700
|
-
|
669
|
+
##
|
670
|
+
# Constructs a submit button from the given options.
|
701
671
|
#
|
702
672
|
# @param [String] source
|
703
673
|
# The source image path for the button.
|
@@ -709,12 +679,12 @@ module Padrino
|
|
709
679
|
# @example
|
710
680
|
# submit_tag "Create", :class => 'success'
|
711
681
|
#
|
712
|
-
# @api public
|
713
682
|
def image_submit_tag(source, options={})
|
714
683
|
options.reverse_merge!(:src => image_path(source))
|
715
684
|
input_tag(:image, options)
|
716
685
|
end
|
717
686
|
|
687
|
+
##
|
718
688
|
# Constructs a hidden field containing a CSRF token.
|
719
689
|
#
|
720
690
|
# @param [String] token
|
@@ -725,17 +695,28 @@ module Padrino
|
|
725
695
|
# @example
|
726
696
|
# csrf_token_field
|
727
697
|
#
|
728
|
-
# @api public
|
729
698
|
def csrf_token_field(token = nil)
|
730
|
-
|
731
|
-
|
732
|
-
end
|
699
|
+
hidden_field_tag csrf_param, :value => csrf_token
|
700
|
+
end
|
733
701
|
|
734
|
-
|
702
|
+
##
|
703
|
+
# Constructs meta tags `csrf-param` and `csrf-token` with the name of the
|
704
|
+
# cross-site request forgery protection parameter and token, respectively.
|
705
|
+
#
|
706
|
+
# @return [String] The meta tags with the CSRF token and the param your app expects it in.
|
707
|
+
#
|
708
|
+
# @example
|
709
|
+
# csrf_meta_tags
|
710
|
+
#
|
711
|
+
def csrf_meta_tags
|
712
|
+
if is_protected_from_csrf?
|
713
|
+
meta_tag(csrf_param, :name => 'csrf-param') <<
|
714
|
+
meta_tag(csrf_token, :name => 'csrf-token')
|
715
|
+
end
|
735
716
|
end
|
736
717
|
|
737
718
|
##
|
738
|
-
# Creates a form containing a single button that submits to the
|
719
|
+
# Creates a form containing a single button that submits to the URL.
|
739
720
|
#
|
740
721
|
# @overload button_to(name, url, options={})
|
741
722
|
# @param [String] caption The text caption.
|
@@ -752,6 +733,8 @@ module Padrino
|
|
752
733
|
# Instructs ujs handler to handle the submit as ajax.
|
753
734
|
# @option options [Symbol] :method
|
754
735
|
# Instructs ujs handler to use different http method (i.e :post, :delete).
|
736
|
+
# @option options [Hash] :submit_options
|
737
|
+
# Hash of any options, that you want to pass to submit_tag (i.e :id, :class)
|
755
738
|
#
|
756
739
|
# @return [String] Form and button html with specified +options+.
|
757
740
|
#
|
@@ -763,22 +746,22 @@ module Padrino
|
|
763
746
|
# # <input type="submit" value="Delete" />
|
764
747
|
# # </form>
|
765
748
|
#
|
766
|
-
# @api public
|
767
749
|
def button_to(*args, &block)
|
768
750
|
name, url = args[0], args[1]
|
769
751
|
options = args.extract_options!
|
770
752
|
options['data-remote'] = 'true' if options.delete(:remote)
|
753
|
+
submit_options = options.delete(:submit_options) || {}
|
771
754
|
if block_given?
|
772
755
|
form_tag(url, options, &block)
|
773
756
|
else
|
774
757
|
form_tag(url, options.merge!(:not_concat => true)) do
|
775
|
-
submit_tag(name)
|
758
|
+
submit_tag(name, submit_options)
|
776
759
|
end
|
777
760
|
end
|
778
761
|
end
|
779
762
|
|
780
763
|
##
|
781
|
-
# Constructs a range tag from the given options
|
764
|
+
# Constructs a range tag from the given options.
|
782
765
|
#
|
783
766
|
# @example
|
784
767
|
# range_field_tag('ranger_with_min_max', :min => 1, :max => 50)
|
@@ -789,14 +772,13 @@ module Padrino
|
|
789
772
|
# @param [Hash] options
|
790
773
|
# The html options for the range field.
|
791
774
|
# @option options [Integer] :min
|
792
|
-
# The min range of the range field
|
775
|
+
# The min range of the range field.
|
793
776
|
# @option options [Integer] :max
|
794
|
-
# The max range of the range field
|
777
|
+
# The max range of the range field.
|
795
778
|
# @option options [range] :range
|
796
|
-
# The range, in lieu of :min and :max. See examples for details
|
779
|
+
# The range, in lieu of :min and :max. See examples for details.
|
797
780
|
# @return [String] The html range field
|
798
781
|
#
|
799
|
-
# @api public
|
800
782
|
def range_field_tag(name, options = {})
|
801
783
|
options.reverse_merge!(:name => name)
|
802
784
|
if range = options.delete(:range)
|
@@ -807,116 +789,131 @@ module Padrino
|
|
807
789
|
|
808
790
|
protected
|
809
791
|
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
792
|
+
##
|
793
|
+
# Returns an array of option items for a select field based on the given collection.
|
794
|
+
#
|
795
|
+
# @param [Array] fields
|
796
|
+
# fields is an array containing the fields to display from each item in the collection.
|
797
|
+
#
|
798
|
+
def options_from_collection(collection, fields)
|
799
|
+
collection.map { |item| [ item.send(fields.first), item.send(fields.last) ] }
|
800
|
+
end
|
817
801
|
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
end
|
802
|
+
##
|
803
|
+
# Returns the options tags for a select based on the given option items.
|
804
|
+
#
|
805
|
+
def options_for_select(option_items, selected_value=nil)
|
806
|
+
return [] if option_items.blank?
|
807
|
+
option_items.map do |caption, value, disabled|
|
808
|
+
value ||= caption
|
809
|
+
disabled ||= false
|
810
|
+
content_tag(:option, caption, :value => value, :selected => option_is_selected?(value, caption, selected_value), :disabled => disabled)
|
828
811
|
end
|
812
|
+
end
|
829
813
|
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
# or:
|
839
|
-
# {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
|
840
|
-
attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
|
841
|
-
disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
|
842
|
-
content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
|
843
|
-
end
|
844
|
-
elsif collection.is_a?(Array)
|
845
|
-
# Array format:
|
846
|
-
# ["Option Label", [:option1, :option2, ...]]
|
814
|
+
##
|
815
|
+
# Returns the optgroups with options tags for a select based on the given :grouped_options items.
|
816
|
+
#
|
817
|
+
def grouped_options_for_select(collection, selected=nil, prompt=false)
|
818
|
+
if collection.is_a?(Hash)
|
819
|
+
collection.map do |key, value|
|
820
|
+
# Hash format:
|
821
|
+
# {:first => [1,2,3], :second => [4,5,6]}
|
847
822
|
# or:
|
848
|
-
#
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
|
853
|
-
end
|
823
|
+
# {:first => [[1,2,3], {:disabled => true}], :second => [4,5,6]}
|
824
|
+
attributes_hash = value.last.is_a?(Hash) ? value.pop : nil
|
825
|
+
disabled ||= attributes_hash && attributes_hash.include?(:disabled) ? attributes_hash[:disabled] : false
|
826
|
+
content_tag :optgroup, options_for_select(value, selected), :label => key, :disabled => disabled
|
854
827
|
end
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
when Array then content_tag(:option, prompt.first, :value => prompt.last)
|
865
|
-
else content_tag(:option, '', :value => '')
|
828
|
+
elsif collection.is_a?(Array)
|
829
|
+
# Array format:
|
830
|
+
# ["Option Label", [:option1, :option2, ...]]
|
831
|
+
# or:
|
832
|
+
# ["Option Label", [:option1, :option2, ...], true]
|
833
|
+
# the last item tells if it is disabled or not. This is keeps it backwards compatible.
|
834
|
+
collection.map do |optgroup|
|
835
|
+
disabled ||= optgroup.count > 2 ? optgroup.pop : false
|
836
|
+
content_tag :optgroup, options_for_select(optgroup.last, selected), :label => optgroup.first, :disabled => disabled
|
866
837
|
end
|
867
838
|
end
|
839
|
+
end
|
868
840
|
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
def configured_form_builder_class(explicit_builder=nil)
|
879
|
-
default_builder = self.respond_to?(:settings) && self.settings.default_builder
|
880
|
-
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
881
|
-
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
882
|
-
configured_builder
|
841
|
+
##
|
842
|
+
# Returns the blank option serving as a prompt if passed.
|
843
|
+
#
|
844
|
+
def blank_option(prompt)
|
845
|
+
return unless prompt
|
846
|
+
case prompt
|
847
|
+
when String then content_tag(:option, prompt, :value => '')
|
848
|
+
when Array then content_tag(:option, prompt.first, :value => prompt.last)
|
849
|
+
else content_tag(:option, '', :value => '')
|
883
850
|
end
|
851
|
+
end
|
884
852
|
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
# @api private
|
892
|
-
def builder_instance(object, settings={})
|
893
|
-
builder_class = configured_form_builder_class(settings.delete(:builder))
|
894
|
-
builder_class.new(self, object, settings)
|
895
|
-
end
|
853
|
+
##
|
854
|
+
# Returns whether the application is being protected from CSRF. Defaults to true.
|
855
|
+
#
|
856
|
+
def is_protected_from_csrf?
|
857
|
+
defined?(settings) ? settings.protect_from_csrf : true
|
858
|
+
end
|
896
859
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
860
|
+
##
|
861
|
+
# Returns the current CSRF token (based on the session). If it doesn't exist,
|
862
|
+
# it will create one and assign it to the session's `csrf` key.
|
863
|
+
#
|
864
|
+
def csrf_token
|
865
|
+
session[:csrf] ||= SecureRandom.hex(32) if defined?(session)
|
866
|
+
end
|
867
|
+
|
868
|
+
##
|
869
|
+
# Returns the param/field name in which your CSRF token should be expected by your
|
870
|
+
# controllers. Defaults to `authenticity_token`.
|
871
|
+
#
|
872
|
+
# Set this in your application with `set :csrf_param, :something_else`.
|
873
|
+
#
|
874
|
+
def csrf_param
|
875
|
+
defined?(settings) && settings.respond_to?(:csrf_param) ?
|
876
|
+
settings.csrf_param : :authenticity_token
|
877
|
+
end
|
878
|
+
|
879
|
+
private
|
880
|
+
##
|
881
|
+
# Returns the FormBuilder class to use based on all available setting sources
|
882
|
+
# If explicitly defined, returns that, otherwise returns defaults.
|
883
|
+
#
|
884
|
+
# @example
|
885
|
+
# configured_form_builder_class(nil) => StandardFormBuilder
|
886
|
+
#
|
887
|
+
def configured_form_builder_class(explicit_builder=nil)
|
888
|
+
default_builder = self.respond_to?(:settings) && self.settings.default_builder
|
889
|
+
configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
|
890
|
+
configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
|
891
|
+
configured_builder
|
892
|
+
end
|
893
|
+
|
894
|
+
##
|
895
|
+
# Returns an initialized builder instance for the given object and settings.
|
896
|
+
#
|
897
|
+
# @example
|
898
|
+
# builder_instance(@account, :nested => { ... }) => <FormBuilder>
|
899
|
+
#
|
900
|
+
def builder_instance(object, settings={})
|
901
|
+
builder_class = configured_form_builder_class(settings.delete(:builder))
|
902
|
+
builder_class.new(self, object, settings)
|
903
|
+
end
|
910
904
|
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
905
|
+
##
|
906
|
+
# Returns whether the option should be selected or not.
|
907
|
+
#
|
908
|
+
# @example
|
909
|
+
# option_is_selected?("red", "Red", ["red", "blue"]) => true
|
910
|
+
# option_is_selected?("red", "Red", ["green", "blue"]) => false
|
911
|
+
#
|
912
|
+
def option_is_selected?(value, caption, selected_values)
|
913
|
+
Array(selected_values).any? do |selected|
|
914
|
+
[value.to_s, caption.to_s].include?(selected.to_s)
|
919
915
|
end
|
920
|
-
|
921
|
-
|
922
|
-
end
|
916
|
+
end
|
917
|
+
end
|
918
|
+
end
|
919
|
+
end
|