diff options
author | Piotr Sarnacki <drogus@gmail.com> | 2013-06-20 15:42:49 -0700 |
---|---|---|
committer | Piotr Sarnacki <drogus@gmail.com> | 2013-06-20 15:42:49 -0700 |
commit | a29f746398e7b0647885343e7f26d977dd251999 (patch) | |
tree | 1e2cd2ee1f8f31812c0acf71350ffe423ca8c5a9 /actionview/lib/action_view/helpers/tags | |
parent | 7c69a829a311a31109939cff19b700b36b97d5c4 (diff) | |
parent | d6b1caa8f2011487c08b414605883f1f220d0aaa (diff) | |
download | rails-a29f746398e7b0647885343e7f26d977dd251999.tar.gz rails-a29f746398e7b0647885343e7f26d977dd251999.tar.bz2 rails-a29f746398e7b0647885343e7f26d977dd251999.zip |
Merge pull request #11032 from strzalek/extract-actionview
Extract ActionView to separate directory
Diffstat (limited to 'actionview/lib/action_view/helpers/tags')
33 files changed, 958 insertions, 0 deletions
diff --git a/actionview/lib/action_view/helpers/tags/base.rb b/actionview/lib/action_view/helpers/tags/base.rb new file mode 100644 index 0000000000..3fe3f4e9df --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/base.rb @@ -0,0 +1,147 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class Base # :nodoc: + include Helpers::ActiveModelInstanceTag, Helpers::TagHelper, Helpers::FormTagHelper + include FormOptionsHelper + + 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 + + # This is what child classes implement. + def render + raise NotImplementedError, "Subclasses must implement a render method" + end + + private + + def value(object) + object.send @method_name if object + end + + def value_before_type_cast(object) + unless object.nil? + method_before_type_cast = @method_name + "_before_type_cast" + + object.respond_to?(method_before_type_cast) ? + object.send(method_before_type_cast) : + value(object) + 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) + if tag_value.nil? + add_default_name_and_id(options) + else + specified_id = options["id"] + add_default_name_and_id(options) + + if specified_id.blank? && options["id"].present? + options["id"] += "_#{sanitized_value(tag_value)}" + end + end + end + + def add_default_name_and_id(options) + if options.has_key?("index") + options["name"] ||= options.fetch("name"){ tag_name_with_index(options["index"], options["multiple"]) } + options["id"] = options.fetch("id"){ tag_id_with_index(options["index"]) } + options.delete("index") + elsif defined?(@auto_index) + options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index, options["multiple"]) } + options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) } + else + options["name"] ||= options.fetch("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(multiple = false) + "#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}" + end + + def tag_name_with_index(index, multiple = false) + "#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}" + 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 + + def sanitized_value(value) + value.to_s.gsub(/\s/, "_").gsub(/[^-\w]/, "").downcase + end + + def select_content_tag(option_tags, options, html_options) + html_options = html_options.stringify_keys + add_default_name_and_id(html_options) + options[:include_blank] ||= true unless options[:prompt] || select_not_required?(html_options) + select = content_tag("select", add_options(option_tags, options, value(object)), html_options) + + if html_options["multiple"] && options.fetch(:include_hidden, true) + tag("input", :disabled => html_options["disabled"], :name => html_options["name"], :type => "hidden", :value => "") + select + else + select + end + end + + def select_not_required?(html_options) + !html_options["required"] || html_options["multiple"] || html_options["size"].to_i > 1 + end + + def add_options(option_tags, options, value = nil) + if options[:include_blank] + option_tags = content_tag_string('option', options[:include_blank].kind_of?(String) ? options[:include_blank] : nil, :value => '') + "\n" + option_tags + end + if value.blank? && options[:prompt] + option_tags = content_tag_string('option', prompt_text(options[:prompt]), :value => '') + "\n" + option_tags + end + option_tags + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/check_box.rb b/actionview/lib/action_view/helpers/tags/check_box.rb new file mode 100644 index 0000000000..6d51f2629a --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/check_box.rb @@ -0,0 +1,64 @@ +require 'action_view/helpers/tags/checkable' + +module ActionView + module Helpers + module Tags # :nodoc: + class CheckBox < Base #:nodoc: + include Checkable + + def initialize(object_name, method_name, template_object, checked_value, unchecked_value, options) + @checked_value = checked_value + @unchecked_value = unchecked_value + super(object_name, method_name, template_object, options) + end + + def render + options = @options.stringify_keys + options["type"] = "checkbox" + options["value"] = @checked_value + options["checked"] = "checked" if input_checked?(object, options) + + if options["multiple"] + add_default_name_and_id_for_value(@checked_value, options) + options.delete("multiple") + else + add_default_name_and_id(options) + end + + include_hidden = options.delete("include_hidden") { true } + checkbox = tag("input", options) + + if include_hidden + hidden = hidden_field_for_checkbox(options) + hidden + checkbox + else + checkbox + end + end + + private + + def checked?(value) + case value + when TrueClass, FalseClass + value == !!@checked_value + when NilClass + false + when String + value == @checked_value + else + if value.respond_to?(:include?) + value.include?(@checked_value) + else + value.to_i == @checked_value.to_i + end + end + end + + def hidden_field_for_checkbox(options) + @unchecked_value ? tag("input", options.slice("name", "disabled", "form").merge!("type" => "hidden", "value" => @unchecked_value)) : "".html_safe + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/checkable.rb b/actionview/lib/action_view/helpers/tags/checkable.rb new file mode 100644 index 0000000000..052e9df662 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/checkable.rb @@ -0,0 +1,16 @@ +module ActionView + module Helpers + module Tags # :nodoc: + module Checkable # :nodoc: + def input_checked?(object, options) + if options.has_key?("checked") + checked = options.delete "checked" + checked == true || checked == "checked" + else + checked?(value(object)) + end + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb new file mode 100644 index 0000000000..52006d856b --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/collection_check_boxes.rb @@ -0,0 +1,43 @@ +require 'action_view/helpers/tags/collection_helpers' + +module ActionView + module Helpers + module Tags # :nodoc: + class CollectionCheckBoxes < Base # :nodoc: + include CollectionHelpers + + class CheckBoxBuilder < Builder # :nodoc: + def check_box(extra_html_options={}) + html_options = extra_html_options.merge(@input_html_options) + @template_object.check_box(@object_name, @method_name, html_options, @value, nil) + end + end + + def render(&block) + rendered_collection = render_collection do |item, value, text, default_html_options| + default_html_options[:multiple] = true + builder = instantiate_builder(CheckBoxBuilder, item, value, text, default_html_options) + + if block_given? + @template_object.capture(builder, &block) + else + render_component(builder) + end + end + + # Append a hidden field to make sure something will be sent back to the + # server if all check boxes are unchecked. + hidden = @template_object.hidden_field_tag("#{tag_name}[]", "", :id => nil) + + rendered_collection + hidden + end + + private + + def render_component(builder) + builder.check_box + builder.label + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/collection_helpers.rb b/actionview/lib/action_view/helpers/tags/collection_helpers.rb new file mode 100644 index 0000000000..388dcf1f13 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/collection_helpers.rb @@ -0,0 +1,84 @@ +module ActionView + module Helpers + module Tags # :nodoc: + module CollectionHelpers # :nodoc: + class Builder # :nodoc: + attr_reader :object, :text, :value + + def initialize(template_object, object_name, method_name, object, + sanitized_attribute_name, text, value, input_html_options) + @template_object = template_object + @object_name = object_name + @method_name = method_name + @object = object + @sanitized_attribute_name = sanitized_attribute_name + @text = text + @value = value + @input_html_options = input_html_options + end + + def label(label_html_options={}, &block) + @template_object.label(@object_name, @sanitized_attribute_name, @text, label_html_options, &block) + end + end + + def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options) + @collection = collection + @value_method = value_method + @text_method = text_method + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + private + + def instantiate_builder(builder_class, item, value, text, html_options) + builder_class.new(@template_object, @object_name, @method_name, item, + sanitize_attribute_name(value), text, value, html_options) + end + + # Generate default options for collection helpers, such as :checked and + # :disabled. + def default_html_options_for_collection(item, value) #:nodoc: + html_options = @html_options.dup + + [:checked, :selected, :disabled].each do |option| + current_value = @options[option] + next if current_value.nil? + + accept = if current_value.respond_to?(:call) + current_value.call(item) + else + Array(current_value).map(&:to_s).include?(value.to_s) + end + + if accept + html_options[option] = true + elsif option == :checked + html_options[option] = false + end + end + + html_options[:object] = @object + html_options + end + + def sanitize_attribute_name(value) #:nodoc: + "#{sanitized_method_name}_#{sanitized_value(value)}" + end + + def render_collection #:nodoc: + @collection.map do |item| + value = value_for_collection(item, @value_method) + text = value_for_collection(item, @text_method) + default_html_options = default_html_options_for_collection(item, value) + additional_html_options = option_html_attributes(item) + + yield item, value, text, default_html_options.merge(additional_html_options) + end.join.html_safe + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb b/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb new file mode 100644 index 0000000000..20be34c1f2 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/collection_radio_buttons.rb @@ -0,0 +1,36 @@ +require 'action_view/helpers/tags/collection_helpers' + +module ActionView + module Helpers + module Tags # :nodoc: + class CollectionRadioButtons < Base # :nodoc: + include CollectionHelpers + + class RadioButtonBuilder < Builder # :nodoc: + def radio_button(extra_html_options={}) + html_options = extra_html_options.merge(@input_html_options) + @template_object.radio_button(@object_name, @method_name, @value, html_options) + end + end + + def render(&block) + render_collection do |item, value, text, default_html_options| + builder = instantiate_builder(RadioButtonBuilder, item, value, text, default_html_options) + + if block_given? + @template_object.capture(builder, &block) + else + render_component(builder) + end + end + end + + private + + def render_component(builder) + builder.radio_button + builder.label + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/collection_select.rb b/actionview/lib/action_view/helpers/tags/collection_select.rb new file mode 100644 index 0000000000..6cb2b2e0d3 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/collection_select.rb @@ -0,0 +1,28 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class CollectionSelect < Base #:nodoc: + def initialize(object_name, method_name, template_object, collection, value_method, text_method, options, html_options) + @collection = collection + @value_method = value_method + @text_method = text_method + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + option_tags_options = { + :selected => @options.fetch(:selected) { value(@object) }, + :disabled => @options[:disabled] + } + + select_content_tag( + options_from_collection_for_select(@collection, @value_method, @text_method, option_tags_options), + @options, @html_options + ) + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/color_field.rb b/actionview/lib/action_view/helpers/tags/color_field.rb new file mode 100644 index 0000000000..d8fc797035 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/color_field.rb @@ -0,0 +1,25 @@ +module ActionView + module Helpers + module Tags # :nodoc: + 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 diff --git a/actionview/lib/action_view/helpers/tags/date_field.rb b/actionview/lib/action_view/helpers/tags/date_field.rb new file mode 100644 index 0000000000..c22be0db29 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/date_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class DateField < DatetimeField # :nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-%m-%d") + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/date_select.rb b/actionview/lib/action_view/helpers/tags/date_select.rb new file mode 100644 index 0000000000..0c4ac40070 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/date_select.rb @@ -0,0 +1,72 @@ +require 'active_support/core_ext/time/calculations' + +module ActionView + module Helpers + module Tags # :nodoc: + class DateSelect < Base # :nodoc: + def initialize(object_name, method_name, template_object, options, html_options) + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + error_wrapping(datetime_selector(@options, @html_options).send("select_#{select_type}").html_safe) + end + + class << self + def select_type + @select_type ||= self.name.split("::").last.sub("Select", "").downcase + end + end + + private + + def select_type + self.class.select_type + end + + def datetime_selector(options, html_options) + datetime = options.fetch(:selected) { value(object) || default_datetime(options) } + @auto_index ||= nil + + options = options.dup + options[:field_name] = @method_name + options[:include_position] = true + options[:prefix] ||= @object_name + options[:index] = @auto_index if @auto_index && !options.has_key?(:index) + + DateTimeSelector.new(datetime, options, html_options) + end + + def default_datetime(options) + return if options[:include_blank] || options[:prompt] + + case options[:default] + when nil + Time.current + when Date, Time + options[:default] + else + default = options[:default].dup + + # Rename :minute and :second to :min and :sec + default[:min] ||= default[:minute] + default[:sec] ||= default[:second] + + time = Time.current + + [:year, :month, :day, :hour, :min, :sec].each do |key| + default[key] ||= time.send(key) + end + + Time.utc( + default[:year], default[:month], default[:day], + default[:hour], default[:min], default[:sec] + ) + end + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/datetime_field.rb b/actionview/lib/action_view/helpers/tags/datetime_field.rb new file mode 100644 index 0000000000..9a2279c611 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/datetime_field.rb @@ -0,0 +1,22 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class DatetimeField < TextField # :nodoc: + def render + options = @options.stringify_keys + options["value"] = @options.fetch("value") { format_date(value(object)) } + options["min"] = format_date(options["min"]) + options["max"] = format_date(options["max"]) + @options = options + super + end + + private + + def format_date(value) + value.try(:strftime, "%Y-%m-%dT%T.%L%z") + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/datetime_local_field.rb b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb new file mode 100644 index 0000000000..b4a74185d1 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/datetime_local_field.rb @@ -0,0 +1,19 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class DatetimeLocalField < DatetimeField # :nodoc: + class << self + def field_type + @field_type ||= "datetime-local" + end + end + + private + + def format_date(value) + value.try(:strftime, "%Y-%m-%dT%T") + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/datetime_select.rb b/actionview/lib/action_view/helpers/tags/datetime_select.rb new file mode 100644 index 0000000000..563de1840e --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/datetime_select.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class DatetimeSelect < DateSelect # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/email_field.rb b/actionview/lib/action_view/helpers/tags/email_field.rb new file mode 100644 index 0000000000..7ce3ccb9bf --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/email_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class EmailField < TextField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/file_field.rb b/actionview/lib/action_view/helpers/tags/file_field.rb new file mode 100644 index 0000000000..476b820d84 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/file_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class FileField < TextField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/grouped_collection_select.rb b/actionview/lib/action_view/helpers/tags/grouped_collection_select.rb new file mode 100644 index 0000000000..2ed4712dac --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/grouped_collection_select.rb @@ -0,0 +1,29 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class GroupedCollectionSelect < Base # :nodoc: + def initialize(object_name, method_name, template_object, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options) + @collection = collection + @group_method = group_method + @group_label_method = group_label_method + @option_key_method = option_key_method + @option_value_method = option_value_method + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + option_tags_options = { + :selected => @options.fetch(:selected) { value(@object) }, + :disabled => @options[:disabled] + } + + select_content_tag( + option_groups_from_collection_for_select(@collection, @group_method, @group_label_method, @option_key_method, @option_value_method, option_tags_options), @options, @html_options + ) + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/hidden_field.rb b/actionview/lib/action_view/helpers/tags/hidden_field.rb new file mode 100644 index 0000000000..c3757c2461 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/hidden_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class HiddenField < TextField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/label.rb b/actionview/lib/action_view/helpers/tags/label.rb new file mode 100644 index 0000000000..35d3ba8434 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/label.rb @@ -0,0 +1,65 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class Label < Base # :nodoc: + def initialize(object_name, method_name, template_object, content_or_options = nil, options = nil) + options ||= {} + + content_is_options = content_or_options.is_a?(Hash) + if content_is_options + options.merge! content_or_options + @content = nil + else + @content = content_or_options + end + + super(object_name, method_name, template_object, options) + end + + def render(&block) + options = @options.stringify_keys + tag_value = options.delete("value") + name_and_id = options.dup + + if name_and_id["for"] + name_and_id["id"] = name_and_id["for"] + else + name_and_id.delete("id") + end + + add_default_name_and_id_for_value(tag_value, name_and_id) + options.delete("index") + options.delete("namespace") + options["for"] = name_and_id["id"] unless options.key?("for") + + if block_given? + content = @template_object.capture(&block) + else + content = if @content.blank? + @object_name.gsub!(/\[(.*)_attributes\]\[\d\]/, '.\1') + method_and_value = tag_value.present? ? "#{@method_name}.#{tag_value}" : @method_name + + if object.respond_to?(:to_model) + key = object.class.model_name.i18n_key + i18n_default = ["#{key}.#{method_and_value}".to_sym, ""] + end + + i18n_default ||= "" + I18n.t("#{@object_name}.#{method_and_value}", :default => i18n_default, :scope => "helpers.label").presence + else + @content.to_s + end + + content ||= if object && object.class.respond_to?(:human_attribute_name) + object.class.human_attribute_name(@method_name) + end + + content ||= @method_name.humanize + end + + label_tag(name_and_id["id"], content, options) + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/month_field.rb b/actionview/lib/action_view/helpers/tags/month_field.rb new file mode 100644 index 0000000000..4c0fb846ee --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/month_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class MonthField < DatetimeField # :nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-%m") + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/number_field.rb b/actionview/lib/action_view/helpers/tags/number_field.rb new file mode 100644 index 0000000000..4f95b1b4de --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/number_field.rb @@ -0,0 +1,18 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class NumberField < TextField # :nodoc: + def render + options = @options.stringify_keys + + if range = options.delete("in") || options.delete("within") + options.update("min" => range.min, "max" => range.max) + end + + @options = options + super + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/password_field.rb b/actionview/lib/action_view/helpers/tags/password_field.rb new file mode 100644 index 0000000000..6099fa6f19 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/password_field.rb @@ -0,0 +1,12 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class PasswordField < TextField # :nodoc: + def render + @options = {:value => nil}.merge!(@options) + super + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/radio_button.rb b/actionview/lib/action_view/helpers/tags/radio_button.rb new file mode 100644 index 0000000000..4849c537a5 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/radio_button.rb @@ -0,0 +1,31 @@ +require 'action_view/helpers/tags/checkable' + +module ActionView + module Helpers + module Tags # :nodoc: + class RadioButton < Base # :nodoc: + include Checkable + + def initialize(object_name, method_name, template_object, tag_value, options) + @tag_value = tag_value + super(object_name, method_name, template_object, options) + end + + def render + options = @options.stringify_keys + options["type"] = "radio" + options["value"] = @tag_value + options["checked"] = "checked" if input_checked?(object, options) + add_default_name_and_id_for_value(@tag_value, options) + tag("input", options) + end + + private + + def checked?(value) + value.to_s == @tag_value.to_s + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/range_field.rb b/actionview/lib/action_view/helpers/tags/range_field.rb new file mode 100644 index 0000000000..f98ae88043 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/range_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class RangeField < NumberField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/search_field.rb b/actionview/lib/action_view/helpers/tags/search_field.rb new file mode 100644 index 0000000000..c09e2f1be7 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/search_field.rb @@ -0,0 +1,24 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class SearchField < TextField # :nodoc: + def render + 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 + + super + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/select.rb b/actionview/lib/action_view/helpers/tags/select.rb new file mode 100644 index 0000000000..d64e2f68ef --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/select.rb @@ -0,0 +1,40 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class Select < Base # :nodoc: + def initialize(object_name, method_name, template_object, choices, options, html_options) + @choices = choices + @choices = @choices.to_a if @choices.is_a?(Range) + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + option_tags_options = { + :selected => @options.fetch(:selected) { value(@object) }, + :disabled => @options[:disabled] + } + + option_tags = if grouped_choices? + grouped_options_for_select(@choices, option_tags_options) + else + options_for_select(@choices, option_tags_options) + end + + select_content_tag(option_tags, @options, @html_options) + end + + private + + # Grouped choices look like this: + # + # [nil, []] + # { nil => [] } + def grouped_choices? + !@choices.empty? && @choices.first.respond_to?(:last) && Array === @choices.first.last + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/tel_field.rb b/actionview/lib/action_view/helpers/tags/tel_field.rb new file mode 100644 index 0000000000..987bb9e67a --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/tel_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TelField < TextField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/text_area.rb b/actionview/lib/action_view/helpers/tags/text_area.rb new file mode 100644 index 0000000000..c81156c0c8 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/text_area.rb @@ -0,0 +1,18 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TextArea < Base # :nodoc: + def render + options = @options.stringify_keys + add_default_name_and_id(options) + + if size = options.delete("size") + options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split) + end + + content_tag("textarea", options.delete('value') || value_before_type_cast(object), options) + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/text_field.rb b/actionview/lib/action_view/helpers/tags/text_field.rb new file mode 100644 index 0000000000..baa5ff768e --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/text_field.rb @@ -0,0 +1,29 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TextField < Base # :nodoc: + def render + options = @options.stringify_keys + options["size"] = options["maxlength"] unless options.key?("size") + options["type"] ||= field_type + options["value"] = options.fetch("value"){ value_before_type_cast(object) } unless field_type == "file" + options["value"] &&= ERB::Util.html_escape(options["value"]) + add_default_name_and_id(options) + tag("input", options) + end + + class << self + def field_type + @field_type ||= self.name.split("::").last.sub("Field", "").downcase + end + end + + private + + def field_type + self.class.field_type + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/time_field.rb b/actionview/lib/action_view/helpers/tags/time_field.rb new file mode 100644 index 0000000000..0e90a3aed7 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/time_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TimeField < DatetimeField # :nodoc: + private + + def format_date(value) + value.try(:strftime, "%T.%L") + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/time_select.rb b/actionview/lib/action_view/helpers/tags/time_select.rb new file mode 100644 index 0000000000..0b06311d25 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/time_select.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TimeSelect < DateSelect # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/time_zone_select.rb b/actionview/lib/action_view/helpers/tags/time_zone_select.rb new file mode 100644 index 0000000000..80d165ec7e --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/time_zone_select.rb @@ -0,0 +1,20 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class TimeZoneSelect < Base # :nodoc: + def initialize(object_name, method_name, template_object, priority_zones, options, html_options) + @priority_zones = priority_zones + @html_options = html_options + + super(object_name, method_name, template_object, options) + end + + def render + select_content_tag( + time_zone_options_for_select(value(@object) || @options[:default], @priority_zones, @options[:model] || ActiveSupport::TimeZone), @options, @html_options + ) + end + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/url_field.rb b/actionview/lib/action_view/helpers/tags/url_field.rb new file mode 100644 index 0000000000..d76340178d --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/url_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class UrlField < TextField # :nodoc: + end + end + end +end diff --git a/actionview/lib/action_view/helpers/tags/week_field.rb b/actionview/lib/action_view/helpers/tags/week_field.rb new file mode 100644 index 0000000000..5b3d0494e9 --- /dev/null +++ b/actionview/lib/action_view/helpers/tags/week_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags # :nodoc: + class WeekField < DatetimeField # :nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-W%W") + end + end + end + end +end |