diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index c4ebedf1b0ab2..46210690cd9c4 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [Edge] (pending)* +* Added all the new HTML5 form types as individual form tag methods (search, url, number, etc) #3646 [Stephen Celis] + * Changed the object used in routing constraints to be an instance of ActionDispatch::Request rather than Rack::Request @@ -13,6 +15,7 @@ "HEAD" and #request_method returns "GET" in HEAD requests). This is for compatibility with Rack::Request + *Rails 3.0.0 [beta 2] (April 1st, 2010)* * #concat is now deprecated in favor of using <%= %> helpers [YK] diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 45f41edcac3b4..932711f9deeb4 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -784,6 +784,56 @@ def check_box(object_name, method, options = {}, checked_value = "1", unchecked_ def radio_button(object_name, method, tag_value, options = {}) InstanceTag.new(object_name, method, self, options.delete(:object)).to_radio_button_tag(tag_value, options) end + + # Returns a text_field of type "search". + def search_field(object_name, method, options = {}) + options = options.stringify_keys + + if options["autosave"] + if options["autosave"] == true + options["autosave"] = request.host.split(".").reverse.join(".") + end + options["results"] ||= 10 + end + + if options["onsearch"] + options["incremental"] = true unless options.has_key?("incremental") + end + + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("search", options) + end + + # Returns a text_field of type "tel". + def telephone_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("tel", options) + end + alias phone_field telephone_field + + # Returns a text_field of type "url". + def url_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("url", options) + end + + # Returns a text_field of type "email". + def email_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("email", options) + end + + # Returns an input tag of type "number". + # + # ==== Options + # * Accepts same options as number_field_tag + def number_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("number", options) + end + + # Returns an input tag of type "range". + # + # ==== Options + # * Accepts same options as range_field_tag + def range_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("range", options) + end end module InstanceTagMethods #:nodoc: @@ -847,6 +897,14 @@ def to_input_field_tag(field_type, options = {}) tag("input", options) end + def to_number_field_tag(field_type, options = {}) + options = options.stringify_keys + if range = options.delete("in") || options.delete("within") + options.update("min" => range.min, "max" => range.max) + end + to_input_field_tag(field_type, options) + end + def to_radio_button_tag(tag_value, options = {}) options = DEFAULT_RADIO_OPTIONS.merge(options.stringify_keys) options["type"] = "radio" diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 0d47c6eecbeb5..10660ecec1150 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -457,6 +457,69 @@ def field_set_tag(legend = nil, options = nil, &block) output.safe_concat("") end + # Creates a text field of type "search". + # + # ==== Options + # * Accepts the same options as text_field_tag. + def search_field_tag(name, value = nil, options = {}) + text_field_tag(name, value, options.stringify_keys.update("type" => "search")) + end + + # Creates a text field of type "tel". + # + # ==== Options + # * Accepts the same options as text_field_tag. + def telephone_field_tag(name, value = nil, options = {}) + text_field_tag(name, value, options.stringify_keys.update("type" => "tel")) + end + alias phone_field_tag telephone_field_tag + + # Creates a text field of type "url". + # + # ==== Options + # * Accepts the same options as text_field_tag. + def url_field_tag(name, value = nil, options = {}) + text_field_tag(name, value, options.stringify_keys.update("type" => "url")) + end + + # Creates a text field of type "email". + # + # ==== Options + # * Accepts the same options as text_field_tag. + def email_field_tag(name, value = nil, options = {}) + text_field_tag(name, value, options.stringify_keys.update("type" => "email")) + end + + # Creates a number field. + # + # ==== Options + # * :min - The minimum acceptable value. + # * :max - The maximum acceptable value. + # * :in - A range specifying the :min and + # :max values. + # * :step - The acceptable value granularity. + # * Otherwise accepts the same options as text_field_tag. + # + # ==== Examples + # number_field_tag 'quantity', nil, :in => 1...10 + # => + def number_field_tag(name, value = nil, options = {}) + options = options.stringify_keys + options["type"] ||= "number" + if range = options.delete("in") || options.delete("within") + options.update("min" => range.min, "max" => range.max) + end + text_field_tag(name, value, options) + end + + # Creates a range form element. + # + # ==== Options + # * Accepts the same options as number_field_tag. + def range_field_tag(name, value = nil, options = {}) + number_field_tag(name, value, options.stringify_keys.update("type" => "range")) + end + private def html_options_for_form(url_for_options, options, *parameters_for_url) returning options.stringify_keys do |html_options| diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 88014a65647a3..d62406c2d3f84 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -349,6 +349,36 @@ def test_text_area_with_size_option ) end + def search_field + expected = %{} + assert_dom_equal(expected, search_field("contact", "notes_query")) + end + + def test_telephone_field + expected = %{} + assert_dom_equal(expected, telephone_field("user", "cell")) + end + + def test_url_field + expected = %{} + assert_dom_equal(expected, url_field("user", "homepage")) + end + + def test_email_field + expected = %{} + assert_dom_equal(expected, email_field("user", "address")) + end + + def test_number_field + expected = %{} + assert_dom_equal(expected, number_field("order", "quantity", :in => 1...10)) + end + + def test_range_input + expected = %{} + assert_dom_equal(expected, range_field("hifi", "volume", :in => 0..11, :step => 0.1)) + end + def test_explicit_name assert_dom_equal( '', text_field("post", "title", "name" => "dont guess") diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 3b8760351e366..ef612b879bf66 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -335,6 +335,36 @@ def test_image_submit_tag_with_confirmation ) end + def test_search_field_tag + expected = %{} + assert_dom_equal(expected, search_field_tag("query")) + end + + def telephone_field_tag + expected = %{} + assert_dom_equal(expected, telephone_field_tag("cell")) + end + + def test_url_field_tag + expected = %{} + assert_dom_equal(expected, url_field_tag("homepage")) + end + + def test_email_field_tag + expected = %{} + assert_dom_equal(expected, email_field_tag("address")) + end + + def test_number_field_tag + expected = %{} + assert_dom_equal(expected, number_field_tag("quantity", nil, :in => 1...10)) + end + + def test_range_input_tag + expected = %{} + assert_dom_equal(expected, range_field_tag("volume", nil, :in => 0..11, :step => 0.1)) + end + def test_pass assert_equal 1, 1 end