Skip to content

Commit

Permalink
Backport the id change to the legacy branch. (#525)
Browse files Browse the repository at this point in the history
* Use option[:id] for label's *for* attribute

If provided, use option `id` to specify `for` attribute on label
for (text, email...) fields, checkbox, radio and select.
Solves #342 issue and supercede #221 and #343 pull requests.

Partially solves #251 (only the part regarding the id).

* Move require mocha/minitest as needed by newer version.

* Fix version of sqlite3 < 1.4 so tests will work.
  • Loading branch information
lcreid committed Mar 1, 2019
1 parent 8f46d28 commit 32206eb
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 8 deletions.
4 changes: 3 additions & 1 deletion bootstrap_form.gemspec
Expand Up @@ -18,7 +18,9 @@ Gem::Specification.new do |s|

s.add_development_dependency "mime-types", "~> 2.6.2"
s.add_development_dependency "rails", ">= 4.0"
s.add_development_dependency "sqlite3"
# sqlite3 1.4.0 breaks the test suite.
# https://github.com/rails/rails/pull/35154
s.add_development_dependency "sqlite3", "~> 1.3.6"
s.add_development_dependency "timecop", "~> 0.7.1"
s.add_development_dependency "mocha"
s.add_development_dependency "appraisal"
Expand Down
16 changes: 10 additions & 6 deletions lib/bootstrap_form/form_builder.rb
Expand Up @@ -134,10 +134,10 @@ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_

if options[:inline]
label_class = " #{label_class}" if label_class
label(label_name, html, class: "checkbox-inline#{disabled_class}#{label_class}")
label(label_name, html, { class: "checkbox-inline#{disabled_class}#{label_class}" }.merge(options[:id].present? ? { for: options[:id] } : {}))
else
content_tag(:div, class: "checkbox#{disabled_class}") do
label(label_name, html, class: label_class)
label(label_name, html, { class: label_class }.merge(options[:id].present? ? { for: options[:id] } : {}))
end
end
end
Expand All @@ -155,10 +155,10 @@ def radio_button_with_bootstrap(name, value, *args)

if options[:inline]
label_class = " #{label_class}" if label_class
label(name, html, class: "radio-inline#{disabled_class}#{label_class}", value: value)
label(name, html, { class: "radio-inline#{disabled_class}#{label_class}", value: value }.merge(options[:id].present? ? { for: options[:id] } : {}))
else
content_tag(:div, class: "radio#{disabled_class}") do
label(name, html, value: value, class: label_class)
label(name, html, { value: value, class: label_class }.merge(options[:id].present? ? { for: options[:id] } : {}))
end
end
end
Expand Down Expand Up @@ -350,11 +350,11 @@ def form_group_builder(method, options, html_options = nil)
label_text ||= options.delete(:label)
end

form_group_options.merge!(label: {
form_group_options[:label] = {
text: label_text,
class: label_class,
skip_required: options.delete(:skip_required)
})
}.merge(css_options[:id].present? ? { for: css_options[:id] } : {})
end

form_group(method, form_group_options) do
Expand All @@ -369,6 +369,10 @@ def convert_form_tag_options(method, options = {})
end

def generate_label(id, name, options, custom_label_col, group_layout)
# id is the caller's options[:id] at the only place this method is called.
# The options argument is a small subset of the options that might have
# been passed to generate_label's caller, and definitely doesn't include
# :id.
options[:for] = id if acts_like_form_tag
classes = [options[:class], label_class]
classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
Expand Down
5 changes: 5 additions & 0 deletions test/bootstrap_checkbox_test.rb
Expand Up @@ -32,6 +32,11 @@ def setup
assert_equivalent_xml expected, @builder.check_box(:terms, label_class: 'btn')
end

test "check_box 'id' attribute is used to specify label 'for' attribute" do
expected = %{<div class="checkbox"><label for="custom_id"><input name="user[terms]" type="hidden" value="0" /><input id="custom_id" type="checkbox" value="1" name="user[terms]" /> Terms</label></div>}
assert_equivalent_xml expected, @builder.check_box(:terms, id: 'custom_id')
end

test "check_box responds to checked_value and unchecked_value arguments" do
expected = %{<div class="checkbox"><label for="user_terms"><input name="user[terms]" type="hidden" value="no" /><input id="user_terms" name="user[terms]" type="checkbox" value="yes" /> I agree to the terms</label></div>}
assert_equivalent_xml expected, @builder.check_box(:terms, {label: 'I agree to the terms'}, 'yes', 'no')
Expand Down
5 changes: 5 additions & 0 deletions test/bootstrap_fields_test.rb
Expand Up @@ -83,6 +83,11 @@ def setup
assert_equivalent_xml expected, @builder.text_field(:email)
end

test "field 'id' attribute is used to specify label 'for' attribute" do
expected = %{<div class="form-group"><label class="control-label required" for="custom_id">Email</label><input id="custom_id" class="form-control" type="text" value="steve@example.com" name="user[email]" /></div>}
assert_equivalent_xml expected, @builder.text_field(:email, id: :custom_id)
end

test "time fields are wrapped correctly" do
expected = %{<div class="form-group"><label class="control-label" for="user_misc">Misc</label><input class="form-control" id="user_misc" name="user[misc]" type="time" /></div>}
assert_equivalent_xml expected, @builder.time_field(:misc)
Expand Down
12 changes: 12 additions & 0 deletions test/bootstrap_radio_button_test.rb
Expand Up @@ -22,6 +22,18 @@ def setup
assert_equivalent_xml expected, @builder.radio_button(:misc, '1', label: 'This is a radio button', label_class: 'btn')
end

test "radio_button 'id' attribute is used to specify label 'for' attribute" do
expected = <<-HTML.strip_heredoc
<div class="radio">
<label for="custom_id">
<input id="custom_id" name="user[misc]" type="radio" value="1" />
This is a radio button
</label>
</div>
HTML
assert_equivalent_xml expected, @builder.radio_button(:misc, '1', label: 'This is a radio button', id: 'custom_id')
end

test "radio_button inline label is set correctly" do
expected = %{<label class="radio-inline" for="user_misc_1"><input id="user_misc_1" name="user[misc]" type="radio" value="1" /> This is a radio button</label>}
assert_equivalent_xml expected, @builder.radio_button(:misc, '1', label: 'This is a radio button', inline: true)
Expand Down
14 changes: 14 additions & 0 deletions test/bootstrap_selects_test.rb
Expand Up @@ -32,6 +32,20 @@ def setup
assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, class: "my-select")
end

test "select 'id' attribute is used to specify label 'for' attribute" do
expected = <<-HTML.strip_heredoc
<div class="form-group">
<label class="control-label" for="custom_id">Status</label>
<select id="custom_id" class="form-control" name="user[status]">
<option value="">Please Select</option>
<option value="1">activated</option>
<option value="2">blocked</option>
</select>
</div>
HTML
assert_equivalent_xml expected, @builder.select(:status, [['activated', 1], ['blocked', 2]], { prompt: "Please Select" }, id: "custom_id")
end

test 'selects with addons are wrapped correctly' do
expected = <<-HTML.strip_heredoc
<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion test/test_helper.rb
Expand Up @@ -2,13 +2,13 @@
require 'diffy'
require 'nokogiri'
require 'equivalent-xml'
require 'mocha/mini_test'

# Configure Rails Environment
ENV["RAILS_ENV"] = "test"

require File.expand_path("../dummy/config/environment.rb", __FILE__)
require "rails/test_help"
require 'mocha/minitest'

Rails.backtrace_cleaner.remove_silencers!

Expand Down

0 comments on commit 32206eb

Please sign in to comment.