mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add HTML5 input[type="color"] helper
This commit is contained in:
parent
513a0525c2
commit
1ce4b5b33d
9 changed files with 70 additions and 2 deletions
|
@ -1,5 +1,7 @@
|
||||||
## Rails 4.0.0 (unreleased) ##
|
## Rails 4.0.0 (unreleased) ##
|
||||||
|
|
||||||
|
* Add `color_field` and `color_field_tag` helpers. *Carlos Galdino*
|
||||||
|
|
||||||
* `assert_generates`, `assert_recognizes`, and `assert_routing` all raise
|
* `assert_generates`, `assert_recognizes`, and `assert_routing` all raise
|
||||||
`Assertion` instead of `RoutingError` *David Chelimsky*
|
`Assertion` instead of `RoutingError` *David Chelimsky*
|
||||||
|
|
||||||
|
|
|
@ -939,6 +939,15 @@ module ActionView
|
||||||
Tags::RadioButton.new(object_name, method, self, tag_value, options).render
|
Tags::RadioButton.new(object_name, method, self, tag_value, options).render
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a text_field of type "color".
|
||||||
|
#
|
||||||
|
# color_field("car", "color")
|
||||||
|
# # => <input id="car_color" name="car[color]" type="color" value="#000000" />
|
||||||
|
#
|
||||||
|
def color_field(object_name, method, options = {})
|
||||||
|
Tags::ColorField.new(object_name, method, self, options).render
|
||||||
|
end
|
||||||
|
|
||||||
# Returns an input of type "search" for accessing a specified attribute (identified by +method+) on an object
|
# Returns an input of type "search" for accessing a specified attribute (identified by +method+) on an object
|
||||||
# assigned to the template (identified by +object_name+). Inputs of type "search" may be styled differently by
|
# assigned to the template (identified by +object_name+). Inputs of type "search" may be styled differently by
|
||||||
# some browsers.
|
# some browsers.
|
||||||
|
|
|
@ -524,6 +524,14 @@ module ActionView
|
||||||
output.safe_concat("</fieldset>")
|
output.safe_concat("</fieldset>")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Creates a text field of type "color".
|
||||||
|
#
|
||||||
|
# ==== Options
|
||||||
|
# * Accepts the same options as text_field_tag.
|
||||||
|
def color_field_tag(name, value = nil, options = {})
|
||||||
|
text_field_tag(name, value, options.stringify_keys.update("type" => "color"))
|
||||||
|
end
|
||||||
|
|
||||||
# Creates a text field of type "search".
|
# Creates a text field of type "search".
|
||||||
#
|
#
|
||||||
# ==== Options
|
# ==== Options
|
||||||
|
|
|
@ -8,6 +8,7 @@ module ActionView
|
||||||
autoload :CollectionCheckBoxes
|
autoload :CollectionCheckBoxes
|
||||||
autoload :CollectionRadioButtons
|
autoload :CollectionRadioButtons
|
||||||
autoload :CollectionSelect
|
autoload :CollectionSelect
|
||||||
|
autoload :ColorField
|
||||||
autoload :DateField
|
autoload :DateField
|
||||||
autoload :DateSelect
|
autoload :DateSelect
|
||||||
autoload :DatetimeSelect
|
autoload :DatetimeSelect
|
||||||
|
|
25
actionpack/lib/action_view/helpers/tags/color_field.rb
Normal file
25
actionpack/lib/action_view/helpers/tags/color_field.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
module ActionView
|
||||||
|
module Helpers
|
||||||
|
module Tags
|
||||||
|
class ColorField < TextField #:nodoc:
|
||||||
|
def render
|
||||||
|
options = @options.stringify_keys
|
||||||
|
options["value"] = @options.fetch("value") { validate_color_string(value(object)) }
|
||||||
|
@options = options
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validate_color_string(string)
|
||||||
|
regex = /#[0-9a-fA-F]{6}/
|
||||||
|
if regex.match(string)
|
||||||
|
string.downcase
|
||||||
|
else
|
||||||
|
"#000000"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -214,3 +214,6 @@ class RenderJsonTestException < Exception
|
||||||
return { :error => self.class.name, :message => self.to_s }.to_json
|
return { :error => self.class.name, :message => self.to_s }.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Car < Struct.new(:color)
|
||||||
|
end
|
||||||
|
|
|
@ -83,6 +83,8 @@ class FormHelperTest < ActionView::TestCase
|
||||||
@post.tags << Tag.new
|
@post.tags << Tag.new
|
||||||
|
|
||||||
@blog_post = Blog::Post.new("And his name will be forty and four.", 44)
|
@blog_post = Blog::Post.new("And his name will be forty and four.", 44)
|
||||||
|
|
||||||
|
@car = Car.new("#000FFF")
|
||||||
end
|
end
|
||||||
|
|
||||||
Routes = ActionDispatch::Routing::RouteSet.new
|
Routes = ActionDispatch::Routing::RouteSet.new
|
||||||
|
@ -610,6 +612,17 @@ class FormHelperTest < ActionView::TestCase
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_color_field_with_valid_hex_color_string
|
||||||
|
expected = %{<input id="car_color" name="car[color]" type="color" value="#000fff" />}
|
||||||
|
assert_dom_equal(expected, color_field("car", "color"))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_color_field_with_invalid_hex_color_string
|
||||||
|
expected = %{<input id="car_color" name="car[color]" type="color" value="#000000" />}
|
||||||
|
@car.color = "#1234TR"
|
||||||
|
assert_dom_equal(expected, color_field("car", "color"))
|
||||||
|
end
|
||||||
|
|
||||||
def test_search_field
|
def test_search_field
|
||||||
expected = %{<input id="contact_notes_query" name="contact[notes_query]" type="search" />}
|
expected = %{<input id="contact_notes_query" name="contact[notes_query]" type="search" />}
|
||||||
assert_dom_equal(expected, search_field("contact", "notes_query"))
|
assert_dom_equal(expected, search_field("contact", "notes_query"))
|
||||||
|
|
|
@ -444,6 +444,11 @@ class FormTagHelperTest < ActionView::TestCase
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_color_field_tag
|
||||||
|
expected = %{<input id="car" name="car" type="color" />}
|
||||||
|
assert_dom_equal(expected, color_field_tag("car"))
|
||||||
|
end
|
||||||
|
|
||||||
def test_search_field_tag
|
def test_search_field_tag
|
||||||
expected = %{<input id="query" name="query" type="search" />}
|
expected = %{<input id="query" name="query" type="search" />}
|
||||||
assert_dom_equal(expected, search_field_tag("query"))
|
assert_dom_equal(expected, search_field_tag("query"))
|
||||||
|
|
|
@ -150,7 +150,7 @@ NOTE: Always use labels for checkbox and radio buttons. They associate text with
|
||||||
|
|
||||||
h4. Other Helpers of Interest
|
h4. Other Helpers of Interest
|
||||||
|
|
||||||
Other form controls worth mentioning are textareas, password fields, hidden fields, search fields, telephone fields, date fields, time fields, URL fields and email fields:
|
Other form controls worth mentioning are textareas, password fields, hidden fields, search fields, telephone fields, date fields, time fields, color fields, URL fields and email fields:
|
||||||
|
|
||||||
<erb>
|
<erb>
|
||||||
<%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
|
<%= text_area_tag(:message, "Hi, nice site", :size => "24x6") %>
|
||||||
|
@ -161,6 +161,7 @@ Other form controls worth mentioning are textareas, password fields, hidden fiel
|
||||||
<%= date_field(:user, :born_on) %>
|
<%= date_field(:user, :born_on) %>
|
||||||
<%= url_field(:user, :homepage) %>
|
<%= url_field(:user, :homepage) %>
|
||||||
<%= email_field(:user, :address) %>
|
<%= email_field(:user, :address) %>
|
||||||
|
<%= color_field(:user, :favorite_color) %>
|
||||||
<%= time_field(:task, :started_at) %>
|
<%= time_field(:task, :started_at) %>
|
||||||
</erb>
|
</erb>
|
||||||
|
|
||||||
|
@ -175,12 +176,13 @@ Output:
|
||||||
<input id="user_born_on" name="user[born_on]" type="date" />
|
<input id="user_born_on" name="user[born_on]" type="date" />
|
||||||
<input id="user_homepage" name="user[homepage]" type="url" />
|
<input id="user_homepage" name="user[homepage]" type="url" />
|
||||||
<input id="user_address" name="user[address]" type="email" />
|
<input id="user_address" name="user[address]" type="email" />
|
||||||
|
<input id="user_favorite_color" name="user[favorite_color]" type="color" value="#000000" />
|
||||||
<input id="task_started_at" name="task[started_at]" type="time" />
|
<input id="task_started_at" name="task[started_at]" type="time" />
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript.
|
Hidden inputs are not shown to the user but instead hold data like any textual input. Values inside them can be changed with JavaScript.
|
||||||
|
|
||||||
IMPORTANT: The search, telephone, date, time, URL, and email inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely "no shortage of solutions for this":https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills, although a couple of popular tools at the moment are "Modernizr":http://www.modernizr.com/ and "yepnope":http://yepnopejs.com/, which provide a simple way to add functionality based on the presence of detected HTML5 features.
|
IMPORTANT: The search, telephone, date, time, color, URL, and email inputs are HTML5 controls. If you require your app to have a consistent experience in older browsers, you will need an HTML5 polyfill (provided by CSS and/or JavaScript). There is definitely "no shortage of solutions for this":https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills, although a couple of popular tools at the moment are "Modernizr":http://www.modernizr.com/ and "yepnope":http://yepnopejs.com/, which provide a simple way to add functionality based on the presence of detected HTML5 features.
|
||||||
|
|
||||||
TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the "Security Guide":security.html#logging.
|
TIP: If you're using password input fields (for any purpose), you might want to configure your application to prevent those parameters from being logged. You can learn about this in the "Security Guide":security.html#logging.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue