forme 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16429cabb255a24eacd8d108a6c0d1ed771581148f5f344a876ceb1da4082a3f
4
- data.tar.gz: 7fc3607cba35093e78bdfb3f6892bd94289c698b6d015e1a701303e5f5435b1a
3
+ metadata.gz: 81ec9ce1b755276902340c709aa7addbd73b6b80252fcf0cbaac236098c62ac1
4
+ data.tar.gz: 35e17dd67304585e027dca62d6181eff1d30a0fcc7aa128879c9d8d54fd78f55
5
5
  SHA512:
6
- metadata.gz: e399a4c2aa701ee112c1c3ed4f95854611781929b5ebcdc7b0c925c703d80b79d5cb77c1b1427e60be98b47e6308aac3cb2a231895874696a8265502fced126a
7
- data.tar.gz: 4397400180f4398ca5a553acf2b2845607952cfadfa8126ea88e473b161b8ac7e04589fcf89a62291b3e6218dbb6cf29d83825090c076d020181d3d1f2b05de7
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="number" value="100000"/>
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="number" value="1"/></label>
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="number" value="2"/></label>
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
- unless @opts[:error_id]
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] === false ? nil : input.opts.fetch(:label_for, id)
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
@@ -333,7 +333,9 @@ module Forme
333
333
  copy_inputs_wrapper_from_wrapper(opts, @opts)
334
334
  yield
335
335
  ensure
336
+ # :nocov:
336
337
  @opts = orig_opts if orig_opts
338
+ # :nocov:
337
339
  end
338
340
 
339
341
  private
@@ -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
- return super unless tag.is_a?(Array)
53
- return super unless tag.first.is_a?(Tag)
54
- return super unless tag.first.type == :legend
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
- first_input = input.opts[:first_input]
57
- attr = first_input.opts[:attr] ||= {}
58
- Forme.attr_classes(attr, 'error')
59
- attr['aria-invalid'] = 'true'
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
- unless @opts[:error_id]
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
- e = errors[ns] || errors[ns.to_s]
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
- if os
436
- vm = @opts[:value_method]
437
- tm = @opts[:text_method]
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
- os.map do |x|
448
- attr = {}
449
- if tm
450
- text = x.send(tm)
451
- val = x.send(vm) if vm
452
- elsif x.is_a?(Array)
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
- yield [text, val, !val.nil? ? cmp.call(val) : cmp.call(text), attr]
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
@@ -6,7 +6,7 @@ module Forme
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Forme, updated for new feature releases of Forme.
9
- MINOR = 1
9
+ MINOR = 2
10
10
 
11
11
  # The patch version of Forme, updated only for bug fixes from the last
12
12
  # feature release.
@@ -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, *| humanize(l)} if opts[:inputs]}
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] = obj.send(field)
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 number inputs for integers.
427
+ # Use inputmode and pattern attributes for integers.
428
428
  def input_integer(sch)
429
- standard_input(:number)
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
- if attr = opts[:attr]
109
- name = attr[:name] || attr['name']
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('[]')