forme 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG +10 -0
- data/README.rdoc +3 -3
- data/lib/forme/bs3.rb +7 -7
- data/lib/forme/form.rb +2 -0
- data/lib/forme/transformers/error_handler.rb +10 -10
- data/lib/forme/transformers/formatter.rb +32 -34
- data/lib/forme/version.rb +1 -1
- data/lib/sequel/plugins/forme.rb +8 -6
- data/lib/sequel/plugins/forme_set.rb +2 -4
- data/spec/bs3_reference_spec.rb +288 -311
- data/spec/bs3_sequel_plugin_spec.rb +152 -152
- data/spec/bs3_spec.rb +234 -205
- data/spec/forme_coverage.rb +1 -0
- data/spec/forme_spec.rb +429 -353
- data/spec/rails_integration_spec.rb +13 -1
- data/spec/roda_integration_spec.rb +20 -2
- data/spec/sequel_helper.rb +3 -1
- data/spec/sequel_i18n_plugin_spec.rb +4 -4
- data/spec/sequel_plugin_spec.rb +252 -149
- data/spec/sequel_set_plugin_spec.rb +6 -0
- data/spec/shared_erb_specs.rb +1 -1
- data/spec/sinatra_integration_spec.rb +26 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81ec9ce1b755276902340c709aa7addbd73b6b80252fcf0cbaac236098c62ac1
|
4
|
+
data.tar.gz: 35e17dd67304585e027dca62d6181eff1d30a0fcc7aa128879c9d8d54fd78f55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16f13f8ba1ba9fdae6b26b80f0b2e1fa2ce9ef520a3a29936597771f9f5424d2b49afc6debdb173e2aee6d672a471bb1aa8cee8e73d82ce7f5d30a1fc8ced578
|
7
|
+
data.tar.gz: 89d6f1ef00b4a9b28b55d9a6f42fb5250d10eaec78a7921d6220451f2fe7ea5c4ecea7907bcef5567e5e1dbcb60ccf2ec52195a6a4bfaacf2c4c353c785e9049
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 2.2.0 (2022-06-28)
|
2
|
+
|
3
|
+
* Use inputmode and pattern attributes instead of type=number for integer fields in the Sequel forme plugin (jeremyevans)
|
4
|
+
|
5
|
+
* Respect explicit nil/false :value option for boolean inputs in the Sequel forme plugin (jeremyevans)
|
6
|
+
|
7
|
+
* In bs3 support, make sure error spans have id referenced by aria-describedby (jeremyevans)
|
8
|
+
|
9
|
+
* Set aria-describedby attribute automatically even if :error_id is given manually (jeremyevans)
|
10
|
+
|
1
11
|
=== 2.1.0 (2022-05-25)
|
2
12
|
|
3
13
|
* Avoid hidden inputs inside tbody tags in subform in the Sequel::Model support, since that results in invalid HTML (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -49,7 +49,7 @@ This results in the following HTML:
|
|
49
49
|
<input id="album_name" name="album[name]" type="text" value="Rising Force"/>
|
50
50
|
</label>
|
51
51
|
<label>Copies Sold:
|
52
|
-
<input id="album_copies_sold" name="album[copies_sold]" type="
|
52
|
+
<input id="album_copies_sold" inputmode="numeric" name="album[copies_sold]" pattern="-?[0-9]*" type="text" value="100000"/>
|
53
53
|
</label>
|
54
54
|
</form>
|
55
55
|
|
@@ -443,12 +443,12 @@ form similar to:
|
|
443
443
|
|
444
444
|
<input id="album_tracks_attributes_0_id" name="album[tracks_attributes][0][id]" type="hidden" value="1"/>
|
445
445
|
<fieldset class="inputs"><legend>Track #1</legend>
|
446
|
-
<label>Number: <input id="album_tracks_attributes_0_number" name="album[tracks_attributes][0][number]" type="
|
446
|
+
<label>Number: <input id="album_tracks_attributes_0_number" inputmode="numeric" name="album[tracks_attributes][0][number]" pattern="-?[0-9]*" type="text" value="1"/></label>
|
447
447
|
<label>Name: <input id="album_tracks_attributes_0_name" name="album[tracks_attributes][0][name]" type="text" value="Blue Hawaii"/></label>
|
448
448
|
</fieldset>
|
449
449
|
<input id="album_tracks_attributes_1_id" name="album[tracks_attributes][1][id]" type="hidden" value="2"/>
|
450
450
|
<fieldset class="inputs"><legend>Track #2</legend>
|
451
|
-
<label>Number: <input id="album_tracks_attributes_1_number" name="album[tracks_attributes][1][number]" type="
|
451
|
+
<label>Number: <input id="album_tracks_attributes_1_number" inputmode="numeric" name="album[tracks_attributes][1][number]" pattern="-?[0-9]*" type="text" value="2"/></label>
|
452
452
|
<label>Name: <input id="album_tracks_attributes_1_name" name="album[tracks_attributes][1][name]" type="text" value="Almost Always True"/></label>
|
453
453
|
</fieldset>
|
454
454
|
|
data/lib/forme/bs3.rb
CHANGED
@@ -24,6 +24,7 @@ module Forme
|
|
24
24
|
attr = attr ? attr.dup : {}
|
25
25
|
Forme.attr_classes(attr, 'help-block with-errors')
|
26
26
|
return [tag] if input.opts[:skip_error_message]
|
27
|
+
attr[:id] ||= input.opts[:error_id]
|
27
28
|
|
28
29
|
case input.type
|
29
30
|
when :submit, :reset
|
@@ -84,11 +85,13 @@ module Forme
|
|
84
85
|
|
85
86
|
Forme.attr_classes(@attr, @opts[:class]) if @opts.has_key?(:class)
|
86
87
|
|
87
|
-
if @opts[:error]
|
88
|
+
if @opts[:error] && input.type != :submit && input.type != :reset
|
88
89
|
# Forme.attr_classes(@attr, 'error')
|
89
90
|
@attr["aria-invalid"] = "true"
|
90
91
|
if @opts.fetch(:error_handler, true)
|
91
|
-
|
92
|
+
if @opts[:error_id]
|
93
|
+
@attr['aria-describedby'] ||= @opts[:error_id]
|
94
|
+
else
|
92
95
|
if id = @attr[:id] || @attr['id']
|
93
96
|
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
94
97
|
@opts[:error_id] = error_id
|
@@ -127,7 +130,7 @@ module Forme
|
|
127
130
|
end
|
128
131
|
|
129
132
|
def _format_set(type, tag_attrs={})
|
130
|
-
raise Error, "can't have radioset with no options" unless @opts[:optgroups] || @opts[:options]
|
133
|
+
raise Error, "can't have radioset or checkboxset with no options" unless @opts[:optgroups] || @opts[:options]
|
131
134
|
key = @opts[:key]
|
132
135
|
name = @opts[:name]
|
133
136
|
id = @opts[:id]
|
@@ -282,7 +285,7 @@ module Forme
|
|
282
285
|
label_attr = input.opts[:label_attr]
|
283
286
|
label_attr = label_attr ? label_attr.dup : {}
|
284
287
|
|
285
|
-
label_attr[:for] = label_attr[:for]
|
288
|
+
label_attr[:for] = label_attr[:for] == false ? nil : input.opts.fetch(:label_for, id)
|
286
289
|
label = input.opts[:label]
|
287
290
|
lpos = input.opts[:label_position] || ([:radio, :checkbox].include?(input.type) ? :after : :before)
|
288
291
|
|
@@ -317,9 +320,6 @@ module Forme
|
|
317
320
|
|
318
321
|
case input.type
|
319
322
|
when :submit, :reset
|
320
|
-
klass.delete('form-group')
|
321
|
-
attr[:class] = klass.sort.uniq.join(' ').strip
|
322
|
-
attr.delete(:class) if attr[:class].empty?
|
323
323
|
[tag]
|
324
324
|
when :radio, :checkbox
|
325
325
|
klass.delete('form-group')
|
data/lib/forme/form.rb
CHANGED
@@ -49,17 +49,17 @@ module Forme
|
|
49
49
|
Forme.register_transformer(:error_handler, :after_legend, new)
|
50
50
|
|
51
51
|
def call(tag, input)
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
if tag.is_a?(Array) && tag.first.is_a?(Tag) && tag.first.type == :legend
|
53
|
+
first_input = input.opts[:first_input]
|
54
|
+
attr = first_input.opts[:attr] ||= {}
|
55
|
+
Forme.attr_classes(attr, 'error')
|
56
|
+
attr['aria-invalid'] = 'true'
|
57
|
+
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
attr['aria-describedby'] = input.opts[:error_id] = "#{first_input.opts[:id]}_error_message"
|
61
|
-
|
62
|
-
tag.insert(1, error_tag(input))
|
59
|
+
tag.insert(1, error_tag(input))
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -220,7 +220,7 @@ module Forme
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def _format_set(type, tag_attrs={})
|
223
|
-
raise Error, "can't have radioset with no options" unless @opts[:optgroups] || @opts[:options]
|
223
|
+
raise Error, "can't have radioset or checkboxset with no options" unless @opts[:optgroups] || @opts[:options]
|
224
224
|
key = @opts[:key]
|
225
225
|
name = @opts[:name]
|
226
226
|
id = @opts[:id]
|
@@ -312,7 +312,9 @@ module Forme
|
|
312
312
|
Forme.attr_classes(@attr, 'error')
|
313
313
|
@attr["aria-invalid"] = "true"
|
314
314
|
if @opts.fetch(:error_handler, true)
|
315
|
-
|
315
|
+
if @opts[:error_id]
|
316
|
+
@attr['aria-describedby'] ||= @opts[:error_id]
|
317
|
+
else
|
316
318
|
if id = @attr[:id] || @attr['id']
|
317
319
|
error_id = @attr['aria-describedby'] ||= "#{id}_error_message"
|
318
320
|
@opts[:error_id] = error_id
|
@@ -397,9 +399,7 @@ module Forme
|
|
397
399
|
|
398
400
|
def set_error_from_namespaced_errors(namespaces, errors, key)
|
399
401
|
namespaces.each do |ns|
|
400
|
-
|
401
|
-
return unless e
|
402
|
-
errors = e
|
402
|
+
return unless errors = errors[ns] || errors[ns.to_s]
|
403
403
|
end
|
404
404
|
|
405
405
|
@opts[:error] = errors.fetch(key){errors.fetch(key.to_s){return}}
|
@@ -432,38 +432,36 @@ module Forme
|
|
432
432
|
# Iterate over the given options, yielding the option text, value, whether it is selected, and any attributes.
|
433
433
|
# The block should return an appropriate tag object.
|
434
434
|
def process_select_options(os)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
sel = @opts[:selected] || @attr.delete(:value)
|
439
|
-
|
440
|
-
if @opts[:multiple]
|
441
|
-
sel = Array(sel)
|
442
|
-
cmp = lambda{|v| sel.include?(v)}
|
443
|
-
else
|
444
|
-
cmp = lambda{|v| v == sel}
|
445
|
-
end
|
435
|
+
vm = @opts[:value_method]
|
436
|
+
tm = @opts[:text_method]
|
437
|
+
sel = @opts[:selected] || @attr.delete(:value)
|
446
438
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
text = x.first
|
454
|
-
val = x.last
|
455
|
-
|
456
|
-
if val.is_a?(Hash)
|
457
|
-
value = val[:value]
|
458
|
-
attr.merge!(val)
|
459
|
-
val = value
|
460
|
-
end
|
461
|
-
else
|
462
|
-
text = x
|
463
|
-
end
|
439
|
+
if @opts[:multiple]
|
440
|
+
sel = Array(sel)
|
441
|
+
cmp = lambda{|v| sel.include?(v)}
|
442
|
+
else
|
443
|
+
cmp = lambda{|v| v == sel}
|
444
|
+
end
|
464
445
|
|
465
|
-
|
446
|
+
os.map do |x|
|
447
|
+
attr = {}
|
448
|
+
if tm
|
449
|
+
text = x.send(tm)
|
450
|
+
val = x.send(vm) if vm
|
451
|
+
elsif x.is_a?(Array)
|
452
|
+
text = x.first
|
453
|
+
val = x.last
|
454
|
+
|
455
|
+
if val.is_a?(Hash)
|
456
|
+
value = val[:value]
|
457
|
+
attr.merge!(val)
|
458
|
+
val = value
|
459
|
+
end
|
460
|
+
else
|
461
|
+
text = x
|
466
462
|
end
|
463
|
+
|
464
|
+
yield [text, val, !val.nil? ? cmp.call(val) : cmp.call(text), attr]
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
data/lib/forme/version.rb
CHANGED
data/lib/sequel/plugins/forme.rb
CHANGED
@@ -95,7 +95,7 @@ module Sequel # :nodoc:
|
|
95
95
|
end
|
96
96
|
|
97
97
|
if grid
|
98
|
-
labels = opts.fetch(:labels){opts[:inputs].map{|l
|
98
|
+
labels = opts.fetch(:labels){opts[:inputs].map{|l,| humanize(l)} if opts[:inputs]}
|
99
99
|
legend = opts.fetch(:legend){humanize(association)}
|
100
100
|
inputs_opts = opts[:inputs_opts] || {}
|
101
101
|
inputs(inputs_opts.merge(:inputs_wrapper=>:table, :nested_inputs_wrapper=>:tr, :wrapper=>:td, :labeler=>nil, :labels=>labels, :legend=>legend), &contents)
|
@@ -363,9 +363,10 @@ module Sequel # :nodoc:
|
|
363
363
|
opts[:as] = (sch[:allow_null] || opts[:required] == false) ? :select : :checkbox
|
364
364
|
end
|
365
365
|
|
366
|
+
v = opts.has_key?(:value) ? opts[:value] : obj.send(field)
|
367
|
+
|
366
368
|
case opts[:as]
|
367
369
|
when :radio
|
368
|
-
v = opts.has_key?(:value) ? opts[:value] : obj.send(field)
|
369
370
|
true_value = opts[:true_value]||'t'
|
370
371
|
false_value = opts[:false_value]||'f'
|
371
372
|
opts[:options] = [[opts[:true_label]||'Yes', {:value=>true_value, :key_id=>'yes'}], [opts[:false_label]||'No', {:value=>false_value, :key_id=>'no'}]]
|
@@ -374,13 +375,12 @@ module Sequel # :nodoc:
|
|
374
375
|
end
|
375
376
|
_input(:radioset, opts)
|
376
377
|
when :select
|
377
|
-
v = opts[:value] || obj.send(field)
|
378
378
|
opts[:value] = (v ? 't' : 'f') unless v.nil?
|
379
379
|
opts[:add_blank] = true unless opts.has_key?(:add_blank)
|
380
380
|
opts[:options] = [[opts[:true_label]||'True', opts[:true_value]||'t'], [opts[:false_label]||'False', opts[:false_value]||'f']]
|
381
381
|
_input(:select, opts)
|
382
382
|
else
|
383
|
-
opts[:checked] =
|
383
|
+
opts[:checked] = v
|
384
384
|
opts[:value] = 't'
|
385
385
|
_input(:checkbox, opts)
|
386
386
|
end
|
@@ -424,9 +424,11 @@ module Sequel # :nodoc:
|
|
424
424
|
end
|
425
425
|
end
|
426
426
|
|
427
|
-
# Use
|
427
|
+
# Use inputmode and pattern attributes for integers.
|
428
428
|
def input_integer(sch)
|
429
|
-
|
429
|
+
opts[:attr][:inputmode] ||= 'numeric'
|
430
|
+
opts[:attr][:pattern] ||= '-?[0-9]*'
|
431
|
+
standard_input(:text)
|
430
432
|
end
|
431
433
|
|
432
434
|
# Use date inputs for dates.
|
@@ -105,10 +105,8 @@ module Sequel # :nodoc:
|
|
105
105
|
opts = input.opts
|
106
106
|
return if SKIP_FORMATTERS.include?(opts.fetch(:formatter){input.form_opts[:formatter]})
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
end
|
111
|
-
return unless name ||= opts[:name] || opts[:key]
|
108
|
+
attr = opts[:attr] || {}
|
109
|
+
return unless name ||= attr[:name] || attr['name'] || opts[:name] || opts[:key]
|
112
110
|
|
113
111
|
# Pull out last component of the name if there is one
|
114
112
|
column = name.to_s.chomp('[]')
|