require 'action_view/helpers/form_tag_helper' module ActionView module Helpers module TextFieldDateHelper # These two handle an object with a method that returns a Date or Time object. def date_text_field(object_name, method, options = {}, html_options = {}) InstanceTag.new(object_name, method, self, options.delete(:object)).to_date_text_field_tag(options, html_options) end def time_text_field(object_name, method, options = {}, html_options = {}) InstanceTag.new(object_name, method, self, options.delete(:object)).to_time_text_field_tag(options, html_options) end # These two handle Date and Time objects. def text_field_date(date = Date.current, options = {}, html_options = {}) DateTimeSelector.new(date, options, html_options).text_field_date end def text_field_time(time = Time.current, options = {}, html_options = {}) DateTimeSelector.new(time, options, html_options).text_field_time end end class DateTimeSelector include ActionView::Helpers::FormTagHelper def text_field_date order = date_order.dup @options[:discard_hour] = true @options[:discard_minute] = true @options[:discard_second] = true @options[:discard_year] ||= true unless order.include?(:year) @options[:discard_month] ||= true unless order.include?(:month) @options[:discard_day] ||= true if @options[:discard_month] || !order.include?(:day) # Save this so we can restore it. original_datetime_separator_separator = @options[:datetime_separator] original_date_separator = @options[:date_separator] @options[:datetime_separator] = "" @options[:date_separator] = " " # If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are # valid (otherwise it could be 31 and February wouldn't be a valid date) if @datetime && @options[:discard_day] && !@options[:discard_month] @datetime = @datetime.change(:day => 1) end [:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) } build_text_field_from_types(order).tap do # Restore. @options[:datetime_separator] = original_datetime_separator_separator @options[:date_separator] = original_date_separator end end def text_field_time order = [] @options[:discard_month] = true @options[:discard_year] = true @options[:discard_day] = true @options[:discard_second] ||= true unless @options[:include_seconds] # Save this so we can restore it. original_datetime_separator = @options[:datetime_separator] original_time_separator = @options[:time_separator] original_date_separator = @options[:date_separator] @options[:datetime_separator] = '' @options[:time_separator] = ':' @options[:date_separator] = " " order += [:year, :month, :day] unless @options[:ignore_date] order += [:hour, :minute] order << :second if @options[:include_seconds] build_text_field_from_types(order).tap do # Restore. @options[:datetime_separator] = original_datetime_separator @options[:date_separator] = original_date_separator @options[:time_separator] = original_time_separator end end def text_field_second unless @options[:use_hidden] || @options[:discard_second] build_text(:second, sec) end end def text_field_minute unless @options[:use_hidden] || @options[:discard_minute] build_text(:minute, min) end end def text_field_hour unless @options[:use_hidden] || @options[:discard_hour] build_text(:hour, hour, :ampm => @options[:ampm]) end end def text_field_day unless @options[:use_hidden] || @options[:discard_day] build_text(:day, day, :leading_zeros => false) end end def text_field_month unless @options[:use_hidden] || @options[:discard_month] build_text(:month, month.nil? ? "" : month_name(month), :leading_zeros => false) end end def text_field_year unless @options[:use_hidden] || @options[:discard_year] build_text(:year, year, :leading_zeros => false) end end def build_text_field_from_types(order) input = '' order.reverse.each do |type| separator = separator(type) unless type == order.first # don't add on last field input.insert(0, separator.to_s + send("text_field_#{type}").to_s) end text_field_tag("", input.html_safe, @html_options).html_safe end def build_text(selected, value, options = {}) unless value.nil? options.reverse_merge!({:leading_zeros => true, :ampm => false}) leading_zeros = options.delete(:leading_zeros) value = leading_zeros ? sprintf("%02d", value) : value text = options[:ampm] ? AMPM_TRANSLATION[value] : value else "" end end end class InstanceTag #:nodoc: def to_date_text_field_tag(options = {}, html_options = {}) datetime_selector(options, html_options).text_field_date.html_safe end def to_time_text_field_tag(options = {}, html_options = {}) datetime_selector(options, html_options).text_field_time.html_safe end end autoload :TextFieldDateHelper include TextFieldDateHelper end end