123456789_123456789_123456789_123456789_123456789_

Class: ActionView::Helpers::DateTimeSelector

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: actionview/lib/action_view/helpers/date_helper.rb

Constant Summary

TagHelper - Included

ARIA_PREFIXES, BOOLEAN_ATTRIBUTES, DATA_PREFIXES, PRE_CONTENT_STRINGS, TAG_TYPES

Class Method Summary

Instance Method Summary

TagHelper - Included

#cdata_section

Returns a CDATA section with the given content.

#class_names
#content_tag

Returns an HTML block tag of type name surrounding the content.

#escape_once

Returns an escaped version of html without affecting existing escaped entities.

#tag

Returns an HTML tag.

#token_list

Returns a string of tokens built from args.

#build_tag_values, #ensure_valid_html5_tag_name, #tag_builder

OutputSafetyHelper - Included

#raw

This method outputs without escaping a string.

#safe_join

This method returns an HTML safe string similar to what Array#join would return.

#to_sentence

Converts the array to a comma-separated sentence where the last element is joined by the connector word.

CaptureHelper - Included

#capture

The capture method extracts part of a template as a string object.

#content_for

Calling content_for stores a block of markup in an identifier for later use.

#content_for?

content_for? checks whether any content has been captured yet using content_for.

#provide

The same as content_for but when used with streaming flushes straight back to the layout.

#with_output_buffer

Use an alternate output buffer for the duration of the block.

Constructor Details

.new(datetime, options = {}, html_options = {}) ⇒ DateTimeSelector

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 727

def initialize(datetime, options = {}, html_options = {})
  @options      = options.dup
  @html_options = html_options.dup
  @datetime     = datetime
  @options[:datetime_separator] ||= " — "
  @options[:time_separator]     ||= " : "
end

Instance Method Details

#build_day_options(selected) (private)

Build select option HTML for day.

build_day_options(2)
#=> "<option value="1">1</option>
    <option value="2" selected="selected">2</option>
    <option value="3">3</option>..."

If day_format: ->(day) { day.ordinalize } option is passed to DateTimeSelector

build_day_options(2)
#=> "<option value="1">1st</option>
    <option value="2" selected="selected">2nd</option>
    <option value="3">3rd</option>..."

If use_two_digit_numbers: true option is passed to DateTimeSelector

build_day_options(2)
#=> "<option value="1">01</option>
    <option value="2" selected="selected">02</option>
    <option value="3">03</option>..."
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1070

def build_day_options(selected)
  select_options = []
  (1..31).each do |value|
    tag_options = { value: value }
    tag_options[:selected] = "selected" if selected == value
    text = day_name(value)
    select_options << ("option", text, tag_options)
  end

  (select_options.join("\n") + "\n").html_safe
end

#build_hidden(type, value) (private)

Builds hidden input tag for date part and value.

build_hidden(:year, 2008)
#=> "<input type="hidden" id="date_year" name="date[year]" value="2008" autocomplete="off" />"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1165

def build_hidden(type, value)
  select_options = {
    type: "hidden",
    id: input_id_from_type(type),
    name: input_name_from_type(type),
    value: value,
    autocomplete: "off"
  }.merge!(@html_options.slice(:disabled))
  select_options[:disabled] = "disabled" if @options[:disabled]

  tag(:input, select_options) + "\n".html_safe
end

#build_options(selected, options = {}) (private)

Build select option HTML from date value and options.

build_options(15, start: 1, end: 31)
#=> "<option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>..."

If use_two_digit_numbers: true option is passed:

build_options(15, start: 1, end: 31, use_two_digit_numbers: true)
#=> "<option value="1">01</option>
    <option value="2">02</option>
    <option value="3">03</option>..."

If :step options is passed:

build_options(15, start: 1, end: 31, step: 2)
#=> "<option value="1">1</option>
    <option value="3">3</option>
    <option value="5">5</option>..."
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1027

def build_options(selected, options = {})
  options = {
    leading_zeros: true, ampm: false, use_two_digit_numbers: false
  }.merge!(options)

  start         = options.delete(:start) || 0
  stop          = options.delete(:end) || 59
  step          = options.delete(:step) || 1
  leading_zeros = options.delete(:leading_zeros)

  select_options = []
  start.step(stop, step) do |i|
    value = leading_zeros ? sprintf("%02d", i) : i
    tag_options = { value: value }
    tag_options[:selected] = "selected" if selected == i
    text = options[:use_two_digit_numbers] ? sprintf("%02d", i) : value
    text = options[:ampm] ? AMPM_TRANSLATION[i] : text
    select_options << ("option", text, tag_options)
  end

  (select_options.join("\n") + "\n").html_safe
end

#build_options_and_select(type, selected, options = {}) (private)

Build full select tag from date type and options.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1003

def build_options_and_select(type, selected, options = {})
  build_select(type, build_options(selected, options))
end

#build_select(type, select_options_as_html) (private)

Builds select tag from date type and HTML select options.

build_select(:month, "<option value="1">January</option>...")
#=> "<select id="post_written_on_2i" name="post[written_on(2i)]">
      <option value="1">January</option>...
    </select>"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1110

def build_select(type, select_options_as_html)
  select_options = {
    id: input_id_from_type(type),
    name: input_name_from_type(type)
  }.merge!(@html_options)
  select_options[:disabled] = "disabled" if @options[:disabled]
  select_options[:class] = css_class_attribute(type, select_options[:class], @options[:with_css_classes]) if @options[:with_css_classes]

  select_html = +"\n"
  select_html << ("option", "", value: "", label: " ") + "\n" if @options[:include_blank]
  select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
  select_html << select_options_as_html

  (("select", select_html.html_safe, select_options) + "\n").html_safe
end

#build_selects_from_types(order) (private)

Given an ordering of datetime components, create the selection HTML and join them with their appropriate separators.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1203

def build_selects_from_types(order)
  select = +""
  first_visible = order.find { |type| !@options[:"discard_#{type}"] }
  order.reverse_each do |type|
    separator = separator(type) unless type == first_visible # don't add before first visible field
    select.insert(0, separator.to_s + public_send("select_#{type}").to_s)
  end
  select.html_safe
end

#build_year_options(selected, options = {}) (private)

Build select option HTML for year.

build_year_options(1998, start: 1998, end: 2000)
#=> "<option value="1998" selected="selected">1998</option>
    <option value="1999">1999</option>
    <option value="2000">2000</option>"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1088

def build_year_options(selected, options = {})
  start = options.delete(:start)
  stop = options.delete(:end)
  step = options.delete(:step)

  select_options = []
  start.step(stop, step) do |value|
    tag_options = { value: value }
    tag_options[:selected] = "selected" if selected == value
    text = year_name(value)
    select_options << ("option", text, tag_options)
  end

  (select_options.join("\n") + "\n").html_safe
end

#css_class_attribute(type, html_options_class, options) (private)

Builds the CSS class value for the select element.

css_class_attribute(:year, 'date optional', { year: 'my-year' })
#=> "date optional my-year"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1130

def css_class_attribute(type, html_options_class, options) # :nodoc:
  css_class = \
    case options
    when Hash
      options[type.to_sym]
    else
      type
    end

  [html_options_class, css_class].compact.join(" ")
end

#date_order (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 985

def date_order
  @date_order ||= @options[:order] || translated_date_order
end

#day_name(number) (private)

Looks up day names by number.

day_name(1) # => 1

If the use_two_digit_numbers: true option is passed to DateTimeSelector:

day_name(1) # => "01"

If the day_format: ->(day) { day.ordinalize } option is passed to DateTimeSelector:

day_name(1) # => "1st"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 925

def day_name(number)
  if day_format_lambda = @options[:day_format]
    day_format_lambda.call(number)
  elsif @options[:use_two_digit_numbers]
    "%02d" % number
  else
    number
  end
end

#input_id_from_type(type) (private)

Returns the id attribute for the input tag.

#=> "post_written_on_1i"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1194

def input_id_from_type(type)
  id = input_name_from_type(type).gsub(/([\[(])|(\]\[)/, "_").gsub(/[\])]/, "")
  id = @options[:namespace] + "_" + id if @options[:namespace]

  id
end

#input_name_from_type(type) (private)

Returns the name attribute for the input tag.

#=> post[written_on(1i)]
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1180

def input_name_from_type(type)
  prefix = @options[:prefix] || ActionView::Helpers::DateTimeSelector::DEFAULT_PREFIX
  prefix += "[#{@options[:index]}]" if @options.has_key?(:index)

  field_name = @options[:field_name] || type.to_s
  if @options[:include_position]
    field_name += "(#{ActionView::Helpers::DateTimeSelector::POSITION[type]}i)"
  end

  @options[:discard_type] ? prefix : "#{prefix}[#{field_name}]"
end

#month_name(number) (private)

Looks up month names by number (1-based):

month_name(1) # => "January"

If the :use_month_numbers option is passed:

month_name(1) # => 1

If the :use_two_digit_numbers option is passed:

month_name(1) # => '01'

If the :add_month_numbers option is passed:

month_name(1) # => "1 - January"

If the :month_format_string option is passed:

month_name(1) # => "January (01)"

depending on the format string.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 956

def month_name(number)
  if @options[:use_month_numbers]
    number
  elsif @options[:use_two_digit_numbers]
    "%02d" % number
  elsif @options[:add_month_numbers]
    "#{number} - #{month_names[number]}"
  elsif format_string = @options[:month_format_string]
    format_string % { number: number, name: month_names[number] }
  else
    month_names[number]
  end
end

#month_names (private)

Returns translated month names, but also ensures that a custom month name array has a leading nil element.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 892

def month_names
  @month_names ||= begin
    month_names = @options[:use_month_names] || translated_month_names
    month_names = [nil, *month_names] if month_names.size < 13
    month_names
  end
end

#prompt_option_tag(type, options) (private)

Builds a prompt option tag with supplied options or from default options.

prompt_option_tag(:month, prompt: 'Select month')
#=> "<option value="">Select month</option>"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1146

def prompt_option_tag(type, options)
  prompt = \
    case options
    when Hash
      default_options = { year: false, month: false, day: false, hour: false, minute: false, second: false }
      default_options.merge!(options)[type.to_sym]
    when String
      options
    else
      I18n.translate(:"datetime.prompts.#{type}", locale: @options[:locale])
    end

  prompt ? ("option", prompt_text(prompt, type), value: "") : ""
end

#prompt_text(prompt, type) (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 878

def prompt_text(prompt, type)
  prompt.kind_of?(String) ? prompt : I18n.translate(:"datetime.prompts.#{type}", locale: @options[:locale])
end

#select_date

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 756

def select_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)

  set_day_if_discarded

  [:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }

  build_selects_from_types(order)
end

#select_datetime

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 735

def select_datetime
  order = date_order.dup
  order -= [:hour, :minute, :second]
  @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)
  @options[:discard_minute] ||= true if @options[:discard_hour]
  @options[:discard_second] ||= true unless @options[:include_seconds] && !@options[:discard_minute]

  set_day_if_discarded

  if @options[:tag] && @options[:ignore_date]
    select_time
  else
    [:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }
    order += [:hour, :minute, :second] unless @options[:discard_hour]

    build_selects_from_types(order)
  end
end

#select_day

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 818

def select_day
  if @options[:use_hidden] || @options[:discard_day]
    build_hidden(:day, day || 1)
  else
    build_select(:day, build_day_options(day))
  end
end

#select_hour

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 806

def select_hour
  if @options[:use_hidden] || @options[:discard_hour]
    build_hidden(:hour, hour)
  else
    options         = {}
    options[:ampm]  = @options[:ampm] || false
    options[:start] = @options[:start_hour] || 0
    options[:end]   = @options[:end_hour] || 23
    build_options_and_select(:hour, hour, options)
  end
end

#select_minute

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 798

def select_minute
  if @options[:use_hidden] || @options[:discard_minute]
    build_hidden(:minute, min)
  else
    build_options_and_select(:minute, min, step: @options[:minute_step])
  end
end

#select_month

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 826

def select_month
  if @options[:use_hidden] || @options[:discard_month]
    build_hidden(:month, month || 1)
  else
    month_options = []
    1.upto(12) do |month_number|
      options = { value: month_number }
      options[:selected] = "selected" if month == month_number
      month_options << ("option", month_name(month_number), options) + "\n"
    end
    build_select(:month, month_options.join)
  end
end

#select_second

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 790

def select_second
  if @options[:use_hidden] || @options[:discard_second]
    build_hidden(:second, sec) if @options[:include_seconds]
  else
    build_options_and_select(:second, sec)
  end
end

#select_time

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 774

def select_time
  order = []

  @options[:discard_month]    = true
  @options[:discard_year]     = true
  @options[:discard_day]      = true
  @options[:discard_second] ||= true unless @options[:include_seconds]

  order += [:year, :month, :day] unless @options[:ignore_date]

  order += [:hour, :minute]
  order << :second if @options[:include_seconds]

  build_selects_from_types(order)
end

#select_year

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 840

def select_year
  if !year || @datetime == 0
    val = "1"
    middle_year = Date.today.year
  else
    val = middle_year = year
  end

  if @options[:use_hidden] || @options[:discard_year]
    build_hidden(:year, val)
  else
    options         = {}
    options[:start] = @options[:start_year] || middle_year - 5
    options[:end]   = @options[:end_year] || middle_year + 5
    options[:step]  = options[:start] < options[:end] ? 1 : -1

    max_years_allowed = @options[:max_years_allowed] || 1000

    if (options[:end] - options[:start]).abs > max_years_allowed
      raise ArgumentError, "There are too many years options to be built. Are you sure you haven't mistyped something? You can provide the :max_years_allowed parameter."
    end

    build_select(:year, build_year_options(val, options))
  end
end

#separator(type) (private)

Returns the separator for a given datetime component.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 1214

def separator(type)
  return "" if @options[:use_hidden]

  case type
  when :year, :month, :day
    @options[:"discard_#{type}"] ? "" : @options[:date_separator]
  when :hour
    (@options[:discard_year] && @options[:discard_day]) ? "" : @options[:datetime_separator]
  when :minute, :second
    @options[:"discard_#{type}"] ? "" : @options[:time_separator]
  end
end

#set_day_if_discarded (private)

If the day is hidden, the day should be set to the 1st so all month and year choices are valid. Otherwise, February 31st or February 29th, 2011 can be selected, which are invalid.

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 884

def set_day_if_discarded
  if @datetime && @options[:discard_day]
    @datetime = @datetime.change(day: 1)
  end
end

#translated_date_order (private)

[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 989

def translated_date_order
  date_order = I18n.translate(:'date.order', locale: @options[:locale], default: [])
  date_order = date_order.map(&:to_sym)

  forbidden_elements = date_order - [:year, :month, :day]
  if forbidden_elements.any?
    raise StandardError,
      "#{@options[:locale]}.date.order only accepts :year, :month and :day"
  end

  date_order
end

#translated_month_names (private)

Returns translated month names.

#=> [nil, "January", "February", "March",
         "April", "May", "June", "July",
         "August", "September", "October",
         "November", "December"]

If :use_short_month option is set

#=> [nil, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 909

def translated_month_names
  key = @options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names'
  I18n.translate(key, locale: @options[:locale])
end

#year_name(number) (private)

Looks up year names by number.

year_name(1998) # => 1998

If the :year_format option is passed:

year_name(1998) # => "Heisei 10"
[ GitHub ]

  
# File 'actionview/lib/action_view/helpers/date_helper.rb', line 977

def year_name(number)
  if year_format_lambda = @options[:year_format]
    year_format_lambda.call(number)
  else
    number
  end
end