module DatePicker::FormTagHelper
Public Instance Methods
date_picker_tag(name, value, options = {}, html_options = nil)
click to toggle source
# File lib/date_picker/form_tag_helper.rb, line 6 def date_picker_tag(name, value, options = {}, html_options = nil) # Clean object and attribute names object_name = name.gsub(/\[\w*\]$/, "") attribute_name = name.gsub(/.*\[(\w*)\]$/, "\\1") # Setup Options option_names = [:time_zone, :format, :type, :default, :min, :max] opts = options.clone html_opts = html_options.clone options||= {} options = opts.slice(*option_names) options = ({ type: :date, time_zone: false, }).merge(options) html_options||= {} # Merge html_options with options html_options = { # Use text-type as default instead of date, since Datepicker should not mix up with native html5 components type: :text, # Generate unique ID with UI id: "date_picker_" + Digest::SHA1.hexdigest(name.to_s)[8..16], name: name, data: html_options[:data] || options[:data] || {} }.merge(opts.except(*option_names)).merge(html_options) # Get the type type = options[:type] # Set default values if !options.key?(:default) case type when :date default = Date.current when :datetime default = DateTime.current when :time default = Time.current end else default = options[:default] end # Override value from html_options if html_options.key?(:value) value = html_options[:value] end # Set default value if blank if value.blank? value = default end # Get Type format if not specified format = nil if options[:format].present? format = options[:format] elsif DatePicker.config.formats.present? format = DatePicker.config.formats[type] end # Apply string format identifier or default format if format.blank? || !format.is_a?(String) case type when :date format_id = format.present? && format.is_a?(Symbol) ? format.to_s : 'default' format = I18n.t('date.formats.' + format_id, default: "%Y-%m-%d") when :datetime format_id = format.present? && format.is_a?(Symbol) ? format.to_s : 'default' format = I18n.t('time.formats.' + format_id, default: "%a, %d %b %Y %H:%M:%S") when :time format_id = format.present? && format.is_a?(Symbol) ? format.to_s : 'only_time' format = I18n.t('time.formats.' + format_id, default: "%H:%M:%S") end else format = format.to_s end # Get Style if options[:style].present? style = options[:style] elsif DatePicker.config.style.present? style = DatePicker.config.style else style = :none end path = File.join(File.dirname(__FILE__), "styles", style.to_s) # Require the selected style and retrieve as object if style && style != 'none' && File.exist?(path + '.rb') require path obj = Object::const_get('DatePicker::Styles::' + style.to_s.classify).new end # Merge with types and options from style template types = [:date] if obj && obj.respond_to?(:types) types = obj.send(:types) end # Mobile Fallback is_mobile = (request.headers["HTTP_USER_AGENT"].present? && request.headers["HTTP_USER_AGENT"] =~ /\b(Mobile|webOS|Android|iPhone|iPad|iPod|Windows Phone|Opera Mobi|Kindle|BackBerry|PlayBook)\b/i).present? if is_mobile case options[:type] when :date return date_field(object_name, attribute_name, html_options.merge({type: 'date', value: value.present? ? value : ''})) when :datetime return datetime_field(object_name, attribute_name, html_options.merge({type: 'datetime-local', value: value.present? ? value.strftime("%Y-%m-%dT%H:%M:%S") : ''})) when :time return time_field(object_name, attribute_name, html_options.merge({type: 'time', value: value.present? ? value.strftime("%H:%M") : ''})) end end # Desktop Fallback if !obj || !types.include?(options[:type]) # Presence of attribute name prevents auto-generating html_options.delete(:name) # Choose the right form helper by type case options[:type] when :date return date_select(object_name, attribute_name, {default: value}, html_options) when :datetime return datetime_select(object_name, attribute_name, {default: value}, html_options) when :time return time_select(object_name, attribute_name, {default: value}, html_options) end end # Get options from implementation if obj.respond_to?(:options) html_options = html_options.merge(obj.send(:options)) end # Get mapping from style if obj.mapping.present? mapping = obj.mapping end # Resolve mapping by identifier if obj.mapping.is_a? Symbol mapping = DatePicker::Mappings.send(obj.mapping) end # Setup picker format picker_format = format.clone # Escape special chars in format if mapping[:__].present? replace = mapping[:__].gsub(/\*/, "\\\\1") # Get strftime patterns keys = mapping.keys.select{ |key| !mapping[key].blank? && !key.to_s.start_with?('__') } # Get picker patterns values = keys.map{ |key| mapping[key] } # Escape any special characters of picker format not preceded by % picker_format.gsub!(/(?<!%)(#{(values.map { |string| Regexp.escape(string) }).join('|')})/i, replace) # Escape strftime patterns not preceded by % picker_format.gsub!(/(?<!%)(#{(keys.map { |string| Regexp.escape(string) }).join('|')})/i, replace) end # If time_zone option is specified, replace timezone identifier with mapping in format if options[:time_zone] # Time zone abbreviation name picker_format.gsub!("%Z", value.present? ? value.to_datetime.strftime("%Z") : "") # Time zone as hour and minute offset from UTC (e.g. +0900) picker_format.gsub!("%z", mapping[:z]) else # Otherwise strip time zone and trim result picker_format.gsub!("%Z", "") picker_format.gsub!("%z", "") picker_format.strip! end # Actually replace patterns mapping.each_pair do |k, v| picker_format.gsub!("%" + k.to_s, v) end # Setup data format pattern if type == :date data_format = "%Y-%m-%d" else data_format = "%Y-%m-%d %H:%M:%S" + ((format.include?("%z") || format.include?("%z")) && options[:time_zone] ? ' %z' : '') end # If time_zone option is specified, replace timezone identifier with mapping in data_format if options[:time_zone] # Time zone abbreviation name data_format.gsub!("%Z", value.present? ? value.to_datetime.strftime("%Z") : "") # Time zone as hour and minute offset from UTC (e.g. +0900) data_format.gsub!("%z", mapping[:z]) end # Replace mappings in data_format mapping.each_pair do |k, v| data_format.gsub!("%" + k.to_s, v) end # Get formatted value formatted_value = value.present? ? I18n.l(value, format: format.to_s) : nil html_options[:value] = formatted_value # Get builder template reference tmpl = obj.template # i18n locale = I18n.locale month_names = I18n.t('date.month_names', default: '') month_names = month_names.present? ? month_names.slice(1, month_names.length - 1) : Date::MONTHNAMES abbr_month_names = I18n.t('date.abbr_month_names', default: '') abbr_month_names = abbr_month_names.present? ? abbr_month_names.slice(1, abbr_month_names.length - 1) : Date::MONTHNAMES day_names = I18n.t('date.day_names', default: Date::DAYNAMES) abbr_day_names = I18n.t('date.abbr_day_names', default: Date::ABBR_DAYNAMES) # Setup timestamp time = value.present? ? value.to_time.utc.to_i * 1000 : 0 # Setup timezone tz = Time.zone if value.present? utc_offset = (value.is_a?(Date) ? value.to_datetime : value).utc_offset tz = ActiveSupport::TimeZone.all.select { |zone| zone.tzinfo.current_period.offset.utc_total_offset === utc_offset }.first end timezone = type === :time && utc_offset === 0 ? 'Etc/UTC' : ActiveSupport::TimeZone::MAPPING[tz.name] # Setup Picker Options camelized_keys = lambda do |h| Hash === h ? Hash[ h.map do |k, v| key = k.to_s().camelize key = key[0, 1].downcase + key[1..-1] [key, camelized_keys[v]] end ] : h end picker_options = camelized_keys[html_options[:data]].to_json # Setup html input input_tag = :input input_id = html_options[:id] input_html = content_tag(input_tag, nil, html_options) # Setup template variables vars = options.merge({ type: type, value: value, locale: locale, picker_format: picker_format, data_format: data_format, name: name, input_id: input_id, html_options: html_options, time: time, time_zone: timezone, input_html: input_html, month_names: month_names, abbr_month_names: abbr_month_names, day_names: day_names, abbr_day_names: abbr_day_names }) # Actually render the picker result = ERB.new(tmpl).result(OpenStruct.new(vars).instance_eval { binding }) # Return picker html return result.html_safe end
datetime_picker_tag(name, value, options = {}, html_options = {})
click to toggle source
# File lib/date_picker/form_tag_helper.rb, line 282 def datetime_picker_tag(name, value, options = {}, html_options = {}) options = options.clone.merge({ type: :datetime }) date_picker_tag(name, value, options, html_options) end
time_picker_tag(name, value, options = {}, html_options = {})
click to toggle source
# File lib/date_picker/form_tag_helper.rb, line 289 def time_picker_tag(name, value, options = {}, html_options = {}) options = options.clone.merge({ type: :time }) date_picker_tag(name, value, options, html_options) end