diff options
Diffstat (limited to 'actionpack/lib/action_view/helpers/tags')
33 files changed, 944 insertions, 0 deletions
diff --git a/actionpack/lib/action_view/helpers/tags/base.rb b/actionpack/lib/action_view/helpers/tags/base.rb new file mode 100644 index 0000000000..e077cd5b3c --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/base.rb @@ -0,0 +1,150 @@ +module ActionView + module Helpers + module Tags + 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["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["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) } + else + options["name"] ||= options.fetch("name"){ options['multiple'] ? tag_name_multiple : tag_name } + 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_multiple + "#{tag_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 + + 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('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('option', prompt_text(options[:prompt]), :value => '') + "\n" + option_tags + end + option_tags + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/check_box.rb b/actionpack/lib/action_view/helpers/tags/check_box.rb new file mode 100644 index 0000000000..9d17a1dde3 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/check_box.rb @@ -0,0 +1,62 @@ +require 'action_view/helpers/tags/checkable' + +module ActionView + module Helpers + module Tags + 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 + when Array + value.include?(@checked_value) + else + value.to_i == @checked_value.to_i + 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/actionpack/lib/action_view/helpers/tags/checkable.rb b/actionpack/lib/action_view/helpers/tags/checkable.rb new file mode 100644 index 0000000000..b97c0c68d7 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/checkable.rb @@ -0,0 +1,16 @@ +module ActionView + module Helpers + module Tags + module Checkable + 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/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb new file mode 100644 index 0000000000..e23f5113fb --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb @@ -0,0 +1,37 @@ +require 'action_view/helpers/tags/collection_helpers' + +module ActionView + module Helpers + module Tags + class CollectionCheckBoxes < Base + include CollectionHelpers + + class CheckBoxBuilder < Builder + 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 + 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? + yield builder + else + builder.check_box + builder.label + 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_multiple, "", :id => nil) + + rendered_collection + hidden + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/collection_helpers.rb b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb new file mode 100644 index 0000000000..4e33e79a36 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb @@ -0,0 +1,82 @@ +module ActionView + module Helpers + module Tags + module CollectionHelpers + class Builder + 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| + next unless current_value = @options[option] + + 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) + + yield item, value, text, default_html_options + end.join.html_safe + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb new file mode 100644 index 0000000000..ba2035f074 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb @@ -0,0 +1,30 @@ +require 'action_view/helpers/tags/collection_helpers' + +module ActionView + module Helpers + module Tags + class CollectionRadioButtons < Base + include CollectionHelpers + + class RadioButtonBuilder < Builder + 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 + render_collection do |item, value, text, default_html_options| + builder = instantiate_builder(RadioButtonBuilder, item, value, text, default_html_options) + + if block_given? + yield builder + else + builder.radio_button + builder.label + end + end + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/collection_select.rb b/actionpack/lib/action_view/helpers/tags/collection_select.rb new file mode 100644 index 0000000000..ec78e6e5f9 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/collection_select.rb @@ -0,0 +1,28 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/color_field.rb b/actionpack/lib/action_view/helpers/tags/color_field.rb new file mode 100644 index 0000000000..6f08f8483a --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/color_field.rb @@ -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 diff --git a/actionpack/lib/action_view/helpers/tags/date_field.rb b/actionpack/lib/action_view/helpers/tags/date_field.rb new file mode 100644 index 0000000000..64c29dea3d --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/date_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags + class DateField < DatetimeField #:nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-%m-%d") + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/date_select.rb b/actionpack/lib/action_view/helpers/tags/date_select.rb new file mode 100644 index 0000000000..5d706087b0 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/date_select.rb @@ -0,0 +1,70 @@ +module ActionView + module Helpers + module Tags + 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 = 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_time( + default[:year], default[:month], default[:day], + default[:hour], default[:min], default[:sec] + ) + end + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/datetime_field.rb b/actionpack/lib/action_view/helpers/tags/datetime_field.rb new file mode 100644 index 0000000000..e407146e96 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/datetime_field.rb @@ -0,0 +1,22 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb b/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb new file mode 100644 index 0000000000..6668d6d718 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/datetime_local_field.rb @@ -0,0 +1,19 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/datetime_select.rb b/actionpack/lib/action_view/helpers/tags/datetime_select.rb new file mode 100644 index 0000000000..a32c840bce --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/datetime_select.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class DatetimeSelect < DateSelect #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/email_field.rb b/actionpack/lib/action_view/helpers/tags/email_field.rb new file mode 100644 index 0000000000..45cde507d7 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/email_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class EmailField < TextField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/file_field.rb b/actionpack/lib/action_view/helpers/tags/file_field.rb new file mode 100644 index 0000000000..59f2ff71b4 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/file_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class FileField < TextField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb new file mode 100644 index 0000000000..507ba8835f --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/grouped_collection_select.rb @@ -0,0 +1,29 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/hidden_field.rb b/actionpack/lib/action_view/helpers/tags/hidden_field.rb new file mode 100644 index 0000000000..a8d13dc1b1 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/hidden_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class HiddenField < TextField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/label.rb b/actionpack/lib/action_view/helpers/tags/label.rb new file mode 100644 index 0000000000..16135fcd5a --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/label.rb @@ -0,0 +1,65 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/month_field.rb b/actionpack/lib/action_view/helpers/tags/month_field.rb new file mode 100644 index 0000000000..3d3c32d847 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/month_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags + class MonthField < DatetimeField #:nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-%m") + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/number_field.rb b/actionpack/lib/action_view/helpers/tags/number_field.rb new file mode 100644 index 0000000000..9cd04434f0 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/number_field.rb @@ -0,0 +1,18 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/password_field.rb b/actionpack/lib/action_view/helpers/tags/password_field.rb new file mode 100644 index 0000000000..6e7a4d3c36 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/password_field.rb @@ -0,0 +1,12 @@ +module ActionView + module Helpers + module Tags + class PasswordField < TextField #:nodoc: + def render + @options = {:value => nil}.merge!(@options) + super + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/radio_button.rb b/actionpack/lib/action_view/helpers/tags/radio_button.rb new file mode 100644 index 0000000000..8a0421f061 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/radio_button.rb @@ -0,0 +1,31 @@ +require 'action_view/helpers/tags/checkable' + +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/range_field.rb b/actionpack/lib/action_view/helpers/tags/range_field.rb new file mode 100644 index 0000000000..47db4680e7 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/range_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class RangeField < NumberField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/search_field.rb b/actionpack/lib/action_view/helpers/tags/search_field.rb new file mode 100644 index 0000000000..818fd4b887 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/search_field.rb @@ -0,0 +1,24 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/select.rb b/actionpack/lib/action_view/helpers/tags/select.rb new file mode 100644 index 0000000000..53a108b7e6 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/select.rb @@ -0,0 +1,41 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/tel_field.rb b/actionpack/lib/action_view/helpers/tags/tel_field.rb new file mode 100644 index 0000000000..87c1f6b6b6 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/tel_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class TelField < TextField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/text_area.rb b/actionpack/lib/action_view/helpers/tags/text_area.rb new file mode 100644 index 0000000000..f74652c5e7 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/text_area.rb @@ -0,0 +1,18 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/text_field.rb b/actionpack/lib/action_view/helpers/tags/text_field.rb new file mode 100644 index 0000000000..024a1a8af2 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/text_field.rb @@ -0,0 +1,29 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/time_field.rb b/actionpack/lib/action_view/helpers/tags/time_field.rb new file mode 100644 index 0000000000..a3941860c9 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/time_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags + class TimeField < DatetimeField #:nodoc: + private + + def format_date(value) + value.try(:strftime, "%T.%L") + end + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/time_select.rb b/actionpack/lib/action_view/helpers/tags/time_select.rb new file mode 100644 index 0000000000..9e97deb706 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/time_select.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class TimeSelect < DateSelect #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/time_zone_select.rb b/actionpack/lib/action_view/helpers/tags/time_zone_select.rb new file mode 100644 index 0000000000..0a176157c3 --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/time_zone_select.rb @@ -0,0 +1,20 @@ +module ActionView + module Helpers + module Tags + 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/actionpack/lib/action_view/helpers/tags/url_field.rb b/actionpack/lib/action_view/helpers/tags/url_field.rb new file mode 100644 index 0000000000..1ffdfe0b3c --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/url_field.rb @@ -0,0 +1,8 @@ +module ActionView + module Helpers + module Tags + class UrlField < TextField #:nodoc: + end + end + end +end diff --git a/actionpack/lib/action_view/helpers/tags/week_field.rb b/actionpack/lib/action_view/helpers/tags/week_field.rb new file mode 100644 index 0000000000..1e13939a0a --- /dev/null +++ b/actionpack/lib/action_view/helpers/tags/week_field.rb @@ -0,0 +1,13 @@ +module ActionView + module Helpers + module Tags + class WeekField < DatetimeField #:nodoc: + private + + def format_date(value) + value.try(:strftime, "%Y-W%W") + end + end + end + end +end |