From 520fe7defea2271cc540e8190a7b9d83d8dfb8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 16 Jan 2012 17:41:24 -0300 Subject: Extract TextFieldTag --- actionpack/lib/action_view/helpers/form_helper.rb | 2 +- actionpack/lib/action_view/helpers/tags.rb | 3 +- .../lib/action_view/helpers/tags/text_field_tag.rb | 114 +++++++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 actionpack/lib/action_view/helpers/tags/text_field_tag.rb diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index b312d72b99..e1244346d4 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -677,7 +677,7 @@ module ActionView # # => # def text_field(object_name, method, options = {}) - InstanceTag.new(object_name, method, self, options.delete(:object)).to_input_field_tag("text", options) + ActionView::Helpers::Tags::TextFieldTag.new(object_name, method, self, options).render end # Returns an input tag of the "password" type tailored for accessing a specified attribute (identified by +method+) on an object diff --git a/actionpack/lib/action_view/helpers/tags.rb b/actionpack/lib/action_view/helpers/tags.rb index a5eef5a34a..f84b5486ae 100644 --- a/actionpack/lib/action_view/helpers/tags.rb +++ b/actionpack/lib/action_view/helpers/tags.rb @@ -1,7 +1,8 @@ module ActionView module Helpers module Tags - autoload :LabelTag, 'action_view/helpers/tags/label_tag' + autoload :LabelTag, 'action_view/helpers/tags/label_tag' + autoload :TextFieldTag, 'action_view/helpers/tags/text_field_tag' end end end diff --git a/actionpack/lib/action_view/helpers/tags/text_field_tag.rb b/actionpack/lib/action_view/helpers/tags/text_field_tag.rb new file mode 100644 index 0000000000..996a153cf8 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/text_field_tag.rb @@ -0,0 +1,114 @@ +module ActionView + module Helpers + module Tags + class TextFieldTag + include Helpers::ActiveModelInstanceTag, Helpers::TagHelper, Helpers::FormTagHelper + + DEFAULT_FIELD_OPTIONS = { "size" => 30 } + + attr_reader :object + + def initialize(object_name, method_name, template_object, options = {}) + @object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup + @template_object = template_object + + @object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]") + @object = retrieve_object(options.delete(:object)) + @options = options + @auto_index = retrieve_autoindex(Regexp.last_match.pre_match) if Regexp.last_match + end + + def render(&block) + options = @options.stringify_keys + options["size"] = options["maxlength"] || DEFAULT_FIELD_OPTIONS["size"] unless options.key?("size") + options = DEFAULT_FIELD_OPTIONS.merge(options) + options["type"] ||= "text" + options["value"] = options.fetch("value"){ value_before_type_cast(object) } + options["value"] &&= ERB::Util.html_escape(options["value"]) + add_default_name_and_id(options) + tag("input", options) + end + + private + + def value_before_type_cast(object) + unless object.nil? + object.respond_to?(@method_name + "_before_type_cast") ? + object.send(@method_name + "_before_type_cast") : + object.send(@method_name) + end + end + + def retrieve_object(object) + if object + object + elsif @template_object.instance_variable_defined?("@#{@object_name}") + @template_object.instance_variable_get("@#{@object_name}") + end + rescue NameError + # As @object_name may contain the nested syntax (item[subobject]) we need to fallback to nil. + nil + end + + def retrieve_autoindex(pre_match) + object = self.object || @template_object.instance_variable_get("@#{pre_match}") + if object && object.respond_to?(:to_param) + object.to_param + else + raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}" + end + end + + def add_default_name_and_id_for_value(tag_value, options) + unless tag_value.nil? + pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase + specified_id = options["id"] + add_default_name_and_id(options) + options["id"] += "_#{pretty_tag_value}" if specified_id.blank? && options["id"].present? + else + add_default_name_and_id(options) + end + end + + def add_default_name_and_id(options) + if options.has_key?("index") + options["name"] ||= tag_name_with_index(options["index"]) + options["id"] = options.fetch("id"){ tag_id_with_index(options["index"]) } + options.delete("index") + elsif defined?(@auto_index) + options["name"] ||= tag_name_with_index(@auto_index) + options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) } + else + options["name"] ||= tag_name + (options['multiple'] ? '[]' : '') + options["id"] = options.fetch("id"){ tag_id } + end + options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence + end + + def tag_name + "#{@object_name}[#{sanitized_method_name}]" + end + + def tag_name_with_index(index) + "#{@object_name}[#{index}][#{sanitized_method_name}]" + end + + def tag_id + "#{sanitized_object_name}_#{sanitized_method_name}" + end + + def tag_id_with_index(index) + "#{sanitized_object_name}_#{index}_#{sanitized_method_name}" + end + + def sanitized_object_name + @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "") + end + + def sanitized_method_name + @sanitized_method_name ||= @method_name.sub(/\?$/,"") + end + end + end + end +end -- cgit v1.2.3