class SimpleForm::Bootstrap::Inputs::DateTimeInput

Inspired by this StackOverflow answer: stackoverflow.com/a/19018501 I have modified this to work with dates AND times, and also to work better with browsers with JavaScript disabled.

Public Instance Methods

input(_ = nil) click to toggle source
# File lib/simple_form/bootstrap/inputs/date_time_input.rb, line 5
  def input(_ = nil)
    text_field_options             = input_html_options.with_indifferent_access
    format                         = text_field_options.delete(:format) || default_format

    # Integrate with Bootstrap's styling
    text_field_options[:class]    << 'form-control'

    hidden_field_options           = text_field_options.deep_dup
    hidden_field_options[:class]  << 'bootstrap-datepicker'
    hidden_field_options[:class]  << 'bootstrap-timepicker' if input_type == :bootstrap_date_time
    hidden_field_options[:id]      = "#{attribute_name}_hidden"
    hidden_field_options[:value] ||= format_date(value(object), format)
    hidden_field_options[:data]    = { 'date-format' => strftime_to_momentjs_format(format) }

    hidden_field_group_classes     = hidden_field_options[:class].dup
    hidden_field_group_classes.delete('form-control')

    
    text_field_options[:value]   ||= value(object).try(:to_s)

    return_string = <<-END_INPUT
      <div class="input-group #{hidden_field_group_classes.join(' ')}" style="display: none">
        #{@builder.hidden_field(attribute_name, hidden_field_options.to_hash)}
        <span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
      </div>
      #{@builder.text_field(attribute_name, text_field_options.to_hash)}
    END_INPUT
    return_string.html_safe
  end

Protected Instance Methods

default_format() click to toggle source

Gets the format suitable for this field.

# File lib/simple_form/bootstrap/inputs/date_time_input.rb, line 38
def default_format
  case input_type
    when :bootstrap_date
      I18n.t('date.formats.default')
    when :bootstrap_date_time
      I18n.t('time.formats.default')
  end
end
format_date(value, format) click to toggle source
# File lib/simple_form/bootstrap/inputs/date_time_input.rb, line 51
def format_date(value, format)
  value.try(:strftime, format)
end
value(object) click to toggle source
# File lib/simple_form/bootstrap/inputs/date_time_input.rb, line 47
def value(object)
  object.send @attribute_name if object
end

Private Instance Methods

strftime_to_momentjs_format(format) click to toggle source

rubocop:disable Style/CyclomaticComplexity, Style/MethodLength

# File lib/simple_form/bootstrap/inputs/date_time_input.rb, line 58
def strftime_to_momentjs_format(format)
  format.gsub(/([^%]%|^%)([_\-\^][a-zA-Z]|[a-zA-Z])/i) do |match|
    last_match = Regexp.last_match(2)

    # Preprocess the last match:
    # - %_m is blank-padding
    # - %-m is no padding
    # - %^B is uppercase
    padding = 0 # zero padding; 1 = blank, 2 = none
    case last_match[0]
      when '_'
        padding = 1
        last_match = last_match[1]
      when '-'
        padding = 2
        last_match = last_match[1]
      when '^'
        last_match = last_match[1]
    end

    specifier =
      case last_match
        when 'a' # Abbreviated day
          'ddd'
        when 'A' # Full day
          'dddd'
        when 'd' # Day of month, with leading 0
          padding == 2 ? 'D' : 'DD'
        when 'u' # Day of year, with leading 0's (3 digits)
          'DDDD'
        when 'w' # Day of week, Sunday = 0
          'd'

        when 'b', 'h' # Abbreviated month
          'MMM'
        when 'B' # Full month
          'MMMM'
        when 'm' # Two digit representation of month (01 = Jan)
          padding == 2 ? 'M' : 'MM'

        when 'y' # Two digit representation of the year
          'YY'
        when 'Y' # Four digit representation of the year
          'YYYY'

        when 'H' # Two digit representation of the hour in 24-hour format
          'HH'
        when 'k' # Two digit representation of the hour in 24-hour format, padded with space
          'H'
        when 'I' # Two digit representation of the hour in 12-hour format
          'hh'
        when 'l' # Two digit representation of the hour in 12-hour format, padded with space
          'h'

        when 'M' # Two digit representation of minute
          'mm'
        when 'p' # Uppercase AM or PM
          'A'
        when 'P' # Lowercase AM or PM
          'a'
        when 'S' # Two digit representation of seconds
          'ss'

        when 'z' # The time zone offset. e.g. -0500
          'ZZ'
        when 'Z' # The time zone offset. e.g. EST
          'z'
        else
          match
      end

    # Strip the % and return the new specifier
    match = Regexp.last_match(1)
    (match.slice(0, match.length - 1) || '') + specifier
  end
end