bh 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +4 -0
- data/README.md +77 -31
- data/bh.gemspec +1 -0
- data/gemfiles/Gemfile.rails-3.x +1 -0
- data/gemfiles/Gemfile.rails-4.x +1 -0
- data/lib/bh/form_builders/form_builder.rb +41 -0
- data/lib/bh/helpers/alert_helper.rb +2 -5
- data/lib/bh/helpers/base_helper.rb +17 -0
- data/lib/bh/helpers/form/base_helper.rb +112 -0
- data/lib/bh/helpers/form/check_box_helper.rb +35 -0
- data/lib/bh/helpers/form/field_helper.rb +15 -0
- data/lib/bh/helpers/form/fields_for_helper.rb +17 -0
- data/lib/bh/helpers/form/fieldset_helper.rb +16 -0
- data/lib/bh/helpers/form/legend_helper.rb +17 -0
- data/lib/bh/helpers/form/radio_button_helper.rb +19 -0
- data/lib/bh/helpers/form/select_helper.rb +16 -0
- data/lib/bh/helpers/form/static_control_helper.rb +43 -0
- data/lib/bh/helpers/form/submit_helper.rb +23 -0
- data/lib/bh/helpers/form_for_helper.rb +30 -0
- data/lib/bh/helpers/glyphicon_helper.rb +5 -5
- data/lib/bh/helpers/modal_helper.rb +2 -3
- data/lib/bh/helpers/panel_helper.rb +5 -5
- data/lib/bh/helpers/panel_row_helper.rb +1 -5
- data/lib/bh/railtie.rb +2 -0
- data/lib/bh/version.rb +1 -1
- data/spec/helpers/form/check_box_helper_spec.rb +95 -0
- data/spec/helpers/form/field_helper_spec.rb +102 -0
- data/spec/helpers/form/fields_for_helper_spec.rb +35 -0
- data/spec/helpers/form/fieldset_helper_spec.rb +32 -0
- data/spec/helpers/form/legend_helper_spec.rb +35 -0
- data/spec/helpers/form/radio_button_helper_spec.rb +67 -0
- data/spec/helpers/form/select_helper_spec.rb +71 -0
- data/spec/helpers/form/static_control_helper_spec.rb +67 -0
- data/spec/helpers/form/submit_helper_spec.rb +30 -0
- data/spec/helpers/form_for_helper_spec.rb +43 -0
- data/spec/helpers/panel_helper_spec.rb +6 -0
- data/spec/spec_helper.rb +29 -1
- metadata +49 -2
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
def self.field_helpers_to_test
|
6
|
+
types = %w(email file number password phone search telephone text url)
|
7
|
+
if defined?(ActionView::VERSION) # only defined in ActionView >=4
|
8
|
+
# types.concat %w(color date datetime datetime_local month time week)
|
9
|
+
end
|
10
|
+
types.map{|type| "#{type}_field"} << "text_area"
|
11
|
+
end
|
12
|
+
|
13
|
+
field_helpers_to_test.each do |form_field|
|
14
|
+
describe form_field do
|
15
|
+
attr_accessor :output_buffer
|
16
|
+
let(:protect_against_forgery?) { false }
|
17
|
+
let(:form) { form_for user, layout: layout, errors: errors, url: '/', &block }
|
18
|
+
let(:user) { User.new }
|
19
|
+
let(:errors) { {} }
|
20
|
+
|
21
|
+
let(:block) { Proc.new {|f| f.send form_field, :name, options} }
|
22
|
+
let(:options) { {} }
|
23
|
+
|
24
|
+
context 'given any layout' do
|
25
|
+
let(:layout) { :whatever }
|
26
|
+
|
27
|
+
specify 'not given a placeholder option, automatically generates one' do
|
28
|
+
expect(form).to include 'placeholder="Name"'
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'given a placeholder option, uses the provided one' do
|
32
|
+
let(:options) { {placeholder: 'Given name'} }
|
33
|
+
it { expect(form).to include 'placeholder="Given name"' }
|
34
|
+
end
|
35
|
+
|
36
|
+
specify 'not given a label option, automatically generates one' do
|
37
|
+
expect(form).to include 'Name</label>'
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'given a label option, uses the provided one' do
|
41
|
+
let(:options) { {label: 'Given name'} }
|
42
|
+
it { expect(form).to include 'Given name</label>' }
|
43
|
+
end
|
44
|
+
|
45
|
+
specify 'not given an error, does not apply has-error to the form group' do
|
46
|
+
expect(form).not_to include 'has-error'
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'given an error' do
|
50
|
+
before { user.errors.add :name, 'cannot be nil' }
|
51
|
+
|
52
|
+
specify 'shows errors and error messages' do
|
53
|
+
expect(form).to include 'has-error'
|
54
|
+
expect(form).to include '<span class="help-block text-left">cannot be nil</span>'
|
55
|
+
end
|
56
|
+
|
57
|
+
specify 'shows error icons (except for number_field)' do
|
58
|
+
expect(form).to include 'has-feedback' unless form_field == 'number_field'
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'given an option to hide error icons, hides error icons' do
|
62
|
+
let(:errors) { {icons: false} }
|
63
|
+
it{ expect(form).not_to include 'has-feedback' }
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'given an option to hide error messages, hides error messages' do
|
67
|
+
let(:errors) { {messages: false} }
|
68
|
+
it{ expect(form).not_to include 'help-block' }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'given a basic layout' do
|
74
|
+
let(:layout) { :basic }
|
75
|
+
specify 'applies form-group to the container, form-control to the input' do
|
76
|
+
expect(form).to match %r{<div class="form-group"><label.+?>Name</label><(input|textarea) class="form-control"}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'given a horizontal layout' do
|
81
|
+
let(:layout) { :horizontal }
|
82
|
+
specify 'applies form-group to the container, form-control to the input, col-sm-3.control-label to the label and col-sm-9 to the field container' do
|
83
|
+
expect(form).to match %r{<div class="form-group"><label class="col-sm-3 control-label".+?>Name</label><div class="col-sm-9"><(input|textarea) class="form-control"}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'given an inline layout' do
|
88
|
+
let(:layout) { :inline }
|
89
|
+
specify 'applies form-group to the container, form-control to the input, sr-only to the label' do
|
90
|
+
expect(form).to match %r{<div class="form-group"><label class="sr-only".+?>Name</label><(input|textarea) class="form-control"}
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'given an error' do
|
94
|
+
before { user.errors.add :name, 'cannot be nil' }
|
95
|
+
|
96
|
+
specify 'applies sr-only to the error message' do
|
97
|
+
expect(form).to include '<span class="help-block text-left sr-only">cannot be nil</span>'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'fields_for' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for User.new, layout: layout, url: '/', &block }
|
8
|
+
let(:layout) { :whatever }
|
9
|
+
let(:block) { Proc.new {|f| f.fields_for :address, options, &fields_block } }
|
10
|
+
let(:options) { {} }
|
11
|
+
let(:title) { nil }
|
12
|
+
let(:fields_block) { Proc.new {|f| f.text_field :street } }
|
13
|
+
|
14
|
+
specify 'adds a <fieldset> that looks like a Bootstrap panel' do
|
15
|
+
expect(form).to include 'fieldset class="panel panel-default">'
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given a title option, uses the provided title' do
|
19
|
+
let(:options) { {title: 'Your address'} }
|
20
|
+
it { expect(form).to include '<div class="panel-heading">Your address</div>' }
|
21
|
+
end
|
22
|
+
|
23
|
+
specify 'not given a title, generates one from the field name' do
|
24
|
+
expect(form).to include '<div class="panel-heading">Address</div>'
|
25
|
+
end
|
26
|
+
|
27
|
+
specify 'given no layout, inherits the layout options of the parent form' do
|
28
|
+
expect(form).to match %r{<div class="form-group"><label for.+?>Street</label>}
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'given a layout, uses its own layout' do
|
32
|
+
let(:options) { {layout: :horizontal} }
|
33
|
+
it { expect(form).to match %r{<div class="form-group"><label class="col-sm-3 control-label" for.+?>Street</label>} }
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'fieldset' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for User.new, layout: layout, url: '/', &block }
|
8
|
+
let(:block) { Proc.new {|f| f.fieldset title, &fieldset_block } }
|
9
|
+
let(:title) { nil }
|
10
|
+
let(:fieldset_block) { Proc.new { 'fieldset content' } }
|
11
|
+
let(:layout) { :whatever }
|
12
|
+
|
13
|
+
specify 'adds a <fieldset> that looks like a Bootstrap panel' do
|
14
|
+
expect(form).to include 'fieldset class="panel panel-default">'
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'given a title, and a non-inline layout, adds the title in the panel heading' do
|
18
|
+
let(:title) { 'Info' }
|
19
|
+
it { expect(form).to include '<div class="panel-heading">Info</div>' }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'given a title, and an inline layout, does not add a panel heading' do
|
23
|
+
let(:layout) { :inline }
|
24
|
+
let(:title) { 'Info' }
|
25
|
+
it { expect(form).not_to include '<div class="panel-heading">Info</div>' }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'not given a title, does not add a panel heading' do
|
29
|
+
let(:title) { '' }
|
30
|
+
it { expect(form).not_to include 'panel-heading' }
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'legend' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for User.new, layout: layout, url: '/', &block }
|
8
|
+
let(:block) { Proc.new {|f| f.legend 'Basic info' } }
|
9
|
+
let(:layout) { :whatever }
|
10
|
+
|
11
|
+
specify 'adds a <legend> to the form' do
|
12
|
+
expect(form).to include 'legend'
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'given a basic layout' do
|
16
|
+
let(:layout) { :basic }
|
17
|
+
specify 'applies form-group to the container' do
|
18
|
+
expect(form).to match %r{<div class="form-group"><legend>Basic info</legend></div>}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'given a horizontal layout' do
|
23
|
+
let(:layout) { :horizontal }
|
24
|
+
specify 'applies form-group to the container, col-sm-12 to the field container' do
|
25
|
+
expect(form).to match %r{<div class="form-group"><div class="col-sm-12"><legend>Basic info</legend></div>}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'given an inline layout' do
|
30
|
+
let(:layout) { :inline }
|
31
|
+
specify 'applies sr-only to the legend' do
|
32
|
+
expect(form).to match %r{<legend class="sr-only">Basic info</legend>}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'radio_button' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for user, layout: layout, errors: errors, url: '/', &block }
|
8
|
+
let(:user) { User.new }
|
9
|
+
let(:errors) { {} }
|
10
|
+
let(:block) { Proc.new {|f| f.radio_button :name, 'Jeremy', options} }
|
11
|
+
let(:options) { {} }
|
12
|
+
|
13
|
+
context 'given any layout' do
|
14
|
+
let(:layout) { :whatever }
|
15
|
+
|
16
|
+
specify 'not given a label option, generates one from the value' do
|
17
|
+
expect(form).to include '> Jeremy</label>'
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'given a label option, uses the provided one' do
|
21
|
+
let(:options) { {label: 'Jerry'} }
|
22
|
+
it { expect(form).to include '> Jerry</label>' }
|
23
|
+
end
|
24
|
+
|
25
|
+
specify 'not given an error, does not apply has-error to the form group' do
|
26
|
+
expect(form).not_to include 'has-error'
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'given an error' do
|
30
|
+
before { user.errors.add :name, 'cannot be nil' }
|
31
|
+
|
32
|
+
specify 'shows errors and error messages' do
|
33
|
+
expect(form).to include 'has-error'
|
34
|
+
expect(form).to include '<span class="help-block text-left">cannot be nil</span>'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'given a basic layout' do
|
40
|
+
let(:layout) { :basic }
|
41
|
+
specify 'applies radio to the container, and an inline label' do
|
42
|
+
expect(form).to match %r{<div class="radio"><label><input.+? /> Jeremy</label></div>}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'given a horizontal layout' do
|
47
|
+
let(:layout) { :horizontal }
|
48
|
+
specify 'applies form-group to the outer container, .col-sm-offset-3.col-sm-9 to the field container, radio to the container, and an inline label' do
|
49
|
+
expect(form).to match %r{<div class="form-group"><div class="col-sm-offset-3 col-sm-9"><div class="radio"><label><input.+? /> Jeremy</label></div></div></div>}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'given an inline layout' do
|
54
|
+
let(:layout) { :inline }
|
55
|
+
specify 'applies radio to the container, and an inline label' do
|
56
|
+
expect(form).to match %r{<div class="radio"><label><input.+? /> Jeremy</label></div>}
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'given an error' do
|
60
|
+
before { user.errors.add :name, 'cannot be nil' }
|
61
|
+
|
62
|
+
specify 'applies sr-only to the error message' do
|
63
|
+
expect(form).to include '<span class="help-block text-left sr-only">cannot be nil</span>'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'select' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for user, layout: layout, errors: errors, url: '/', &block }
|
8
|
+
let(:user) { User.new }
|
9
|
+
let(:errors) { {} }
|
10
|
+
let(:block) { Proc.new {|f| f.select :name, [['Jeremy', 1]], options} }
|
11
|
+
let(:options) { {} }
|
12
|
+
|
13
|
+
context 'given any layout' do
|
14
|
+
let(:layout) { :whatever }
|
15
|
+
|
16
|
+
specify 'not given a label option, automatically generates one' do
|
17
|
+
expect(form).to include 'Name</label>'
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'given a label option, uses the provided one' do
|
21
|
+
let(:options) { {label: 'Given name'} }
|
22
|
+
it { expect(form).to include 'Given name</label>' }
|
23
|
+
end
|
24
|
+
|
25
|
+
specify 'not given an error, does not apply has-error to the form group' do
|
26
|
+
expect(form).not_to include 'has-error'
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'given an error' do
|
30
|
+
before { user.errors.add :name, 'cannot be nil' }
|
31
|
+
|
32
|
+
specify 'shows errors and error messages' do
|
33
|
+
expect(form).to include 'has-error'
|
34
|
+
expect(form).to include '<span class="help-block text-left">cannot be nil</span>'
|
35
|
+
end
|
36
|
+
|
37
|
+
specify 'does not show error icons' do
|
38
|
+
expect(form).not_to include 'has-feedback'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'given a basic layout' do
|
44
|
+
let(:layout) { :basic }
|
45
|
+
specify 'applies form-group to the container, form-control to the input' do
|
46
|
+
expect(form).to match %r{<div class="form-group"><label.+?>Name</label><select class="form-control"}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'given a horizontal layout' do
|
51
|
+
let(:layout) { :horizontal }
|
52
|
+
specify 'applies form-group to the container, form-control to the input, col-sm-3.control-label to the label and col-sm-9 to the field container' do
|
53
|
+
expect(form).to match %r{<div class="form-group"><label class="col-sm-3 control-label".+?>Name</label><div class="col-sm-9"><select class="form-control"}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'given an inline layout' do
|
58
|
+
let(:layout) { :inline }
|
59
|
+
specify 'applies form-group to the container, form-control to the input, sr-only to the label' do
|
60
|
+
expect(form).to match %r{<div class="form-group"><label class="sr-only".+?>Name</label><select class="form-control"}
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'given an error' do
|
64
|
+
before { user.errors.add :name, 'cannot be nil' }
|
65
|
+
|
66
|
+
specify 'applies sr-only to the error message' do
|
67
|
+
expect(form).to include '<span class="help-block text-left sr-only">cannot be nil</span>'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'static_control' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for User.new, layout: layout, url: '/', &block }
|
8
|
+
let(:block) { Proc.new {|f| f.static_control 'user@example.com', options } }
|
9
|
+
let(:options) { {} }
|
10
|
+
|
11
|
+
context 'given any layout' do
|
12
|
+
let(:layout) { :whatever }
|
13
|
+
|
14
|
+
specify 'adds a paragraph with the static control' do
|
15
|
+
expect(form).to include '<div class="form-group"'
|
16
|
+
expect(form).to include '<p class="form-control-static">user@example.com</p>'
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'given a label option, uses the provided one' do
|
20
|
+
let(:options) { {label: 'Email'} }
|
21
|
+
it { expect(form).to include 'Email</label>' }
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'given the text as a block' do
|
25
|
+
let(:block) { Proc.new {|f| f.static_control(label: 'Email') { 'user@example.com' } } }
|
26
|
+
|
27
|
+
specify 'behaves in the same way' do
|
28
|
+
expect(form).to include '<div class="form-group"'
|
29
|
+
expect(form).to include '<p class="form-control-static">user@example.com</p>'
|
30
|
+
expect(form).to include 'Email</label>'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'given a basic layout and a label' do
|
36
|
+
let(:layout) { :basic }
|
37
|
+
let(:options) { {label: 'Email'} }
|
38
|
+
specify 'uses the provided label' do
|
39
|
+
expect(form).to include '<label>Email</label><p'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'given a horizontal layout' do
|
44
|
+
let(:layout) { :horizontal }
|
45
|
+
|
46
|
+
context 'and a label' do
|
47
|
+
let(:options) { {label: 'Email'} }
|
48
|
+
|
49
|
+
specify 'applies col-sm-9 to the field container and col-sm-3 to the label' do
|
50
|
+
expect(form).to include '<label class="col-sm-3 control-label">Email</label><div class="col-sm-9"><p'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
specify 'and no label, applies col-sm-9.col-sm-offset-3 to the field container' do
|
55
|
+
expect(form).to include '<div class="col-sm-9 col-sm-offset-3"><p'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'given an inline layout and a label' do
|
60
|
+
let(:layout) { :inline }
|
61
|
+
let(:options) { {label: 'Email'} }
|
62
|
+
|
63
|
+
specify 'applies sr-only to the label' do
|
64
|
+
expect(form).to include '<label class="sr-only">Email</label>'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'bh/helpers/form_for_helper'
|
3
|
+
include Bh::FormForHelper
|
4
|
+
|
5
|
+
describe 'submit' do
|
6
|
+
let(:protect_against_forgery?) { false }
|
7
|
+
let(:form) { form_for User.new, layout: layout, url: '/', &block }
|
8
|
+
let(:block) { Proc.new {|f| f.submit 'Save', options} }
|
9
|
+
let(:options) { {} }
|
10
|
+
|
11
|
+
context 'given any layout' do
|
12
|
+
let(:layout) { :whatever }
|
13
|
+
|
14
|
+
specify 'applies .btn.btn-primary to the button' do
|
15
|
+
expect(form).to include 'input class="btn btn-primary"'
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given a context option, applies the context class' do
|
19
|
+
let(:options) { {context: :info} }
|
20
|
+
it { expect(form).to include 'input class="btn btn-info"' }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'given a horizontal layout' do
|
25
|
+
let(:layout) { :horizontal }
|
26
|
+
specify 'applies form-group to the container, col-sm-offset-3.col-sm-9 to the field container' do
|
27
|
+
expect(form).to match %r{<div class="form-group"><div class="col-sm-offset-3 col-sm-9"><input}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|