module Storefront class Form module Inputs def input_for(key, options) send(:"#{options.delete(:as)}_input", key, options) end def default_input_type(method, options = {}) #:nodoc: if column = column_for(method) # Special cases where the column type doesn't map to an input method. case column.type when :string return :password if method.to_s =~ /password/ return :country if method.to_s =~ /country$/ return :time_zone if method.to_s =~ /time_zone/ return :email if method.to_s =~ /email/ return :url if method.to_s =~ /^url$|^website$|_url$/ return :phone if method.to_s =~ /(phone|fax)/ return :search if method.to_s =~ /^search$/ when :integer return :select if reflection_for(method) return :numeric when :float, :decimal return :numeric when :timestamp return :datetime end # Try look for hints in options hash. Quite common senario: Enum keys stored as string in the database. return :select if column.type == :string && options.key?(:collection) # Try 3: Assume the input name will be the same as the column type (e.g. string_input). return column.type else if @object return :select if reflection_for(method) return :file if is_file?(method, options) end return :select if options.key?(:collection) return :password if method.to_s =~ /password/ return :string end end def is_file?(method, options = {}) @files ||= {} @files[method] ||= (options[:as].present? && options[:as] == :file) || begin file = @object.send(method) if @object && @object.respond_to?(method) file && file_methods.any?{|m| file.respond_to?(m)} end end def file_methods [:file?, :public_filename, :filename] end def base_input(input_type, key, options = {}, &block) if [:numeric, :string, :password, :text, :phone, :url, :email].include?(input_type) attributes = default_string_options(key, input_type).merge(options[:input_attributes]) else attributes = options[:input_attributes] end merge_class! attributes, key.to_s, options[:class] attributes[:required] = true if options[:required] == true template.capture_haml do template.haml_tag :input, attributes.merge(:type => input_type), &block end end def core_input(tag, *args, &block) options = args.extract_options! attributes = options[:input_attributes] attributes[:required] = true if options[:required] == true template.capture_haml do if block_given? template.haml_tag tag, attributes, &block else template.haml_tag tag, args.shift, attributes end end end # autofocus, pattern, placeholder, title, size, data-validate, data-validate-match, data-validate-unique def string_input(key, attributes = {}) base_input :string, key, attributes end # maxlength, placeholder, required, wrap, readonly def textarea_input(key, options = {}) attributes = options[:input_attributes] value = attributes.delete(:value) core_input :textarea, value, attributes end alias_method :text_input, :textarea_input def checkbox_input(key, attributes = {}) hidden_input key, attributes.merge(:value => 0) base_input :checkbox, key, attributes.merge(:value => 1) end # prompt, blank, multiple def select_input(key, options = {}) collection = Array(options.delete(:collection) || []) if options[:include_blank] != false prompt = options[:prompt] || "" collection = [[prompt, ""]] + collection end attributes = options[:input_attributes] selected = attributes.delete(:value) core_input :select, options do collection.map do |item| name, options = item, {} case item when Array name = item[0] options[:value] = item[1] when Hash name = item[:name] options[:value] = item[:value] else options[:value] = item end options[:selected] = "true" if selected.present? && options[:value] == selected template.haml_tag :option, name, options end end end def hidden_input(key, attributes = {}) base_input :hidden, key, attributes end def number_input(key, attributes = {}) base_input :string, key, attributes.merge(:class => "number", "data-type" => "number") end def search_input(key, attributes = {}) base_input :search, key, merge_class(attributes, "search").merge("data-type" => "search") end def boolean_input(key, attributes = {}) select_input(key, attributes.merge(:collection => [["Yes", "1"], ["No", "0"]])) #checkbox_input(key, attributes = {}) end # accept, maxlength="2" def file_input(key, attributes = {}) base_input :file, key, attributes end def password_input(key, attributes = {}) base_input :password, key, attributes end def email_input(key, attributes = {}) base_input :email, key, attributes end def url_input(key, attributes = {}) base_input :url, key, attributes end def phone_input(key, attributes = {}) base_input :tel, key, attributes.merge(:class => "phone") end def fax_input(key, attributes = {}) base_input :tel, key, attributes.merge(:class => "phone fax") end def date_input(key, attributes = {}) base_input :string, key, attributes.merge(:class => "date", "data-type" => "date") end def money_input(key, attributes = {}) base_input :string, key, merge_class(attributes, "money").merge("data-type" => "money") end def percent_input(key, attributes = {}) base_input :string, key, merge_class(attributes, "percent").merge("data-type" => "percent") end def watched_input(key, attributes = {}) text_input key, merge_class(attributes, "watch-characters").merge(:"data-character-count" => (attributes.delete(:count) || 100)) # haml_tag :figure, :class => "watched" end def color_input(key, attributes = {}) end def range_input(key, attributes = {}) end def autocomplete_input(key, attributes = {}) end def date_range_input(key, attributes = {}) end def slider_input(key, attributes = {}) end def state_input(key, attributes = {}) end def partial(key, attributes = {}) end def input_id(attribute, name = "input") ([keys] + [@index ? @index.to_s : nil, attribute]).compact.join("-").gsub("_", "-") + "-#{name}" end def input_name(attribute, options = {}) param_for([keys] + [@index ? @index.to_s : nil, attribute]) end def input_value(attribute, default = nil) return default if default.present? if object.respond_to?(attribute) object.send(attribute) else nil end end ## FORMTASTIC STUFF def create_boolean_collection(options) #:nodoc: options[:true] ||= ::Formtastic::I18n.t(:yes) options[:false] ||= ::Formtastic::I18n.t(:no) options[:value_as_class] = true unless options.key?(:value_as_class) [ [ options.delete(:true), true], [ options.delete(:false), false ] ] end def validation_max_limit 255 end def default_text_field_size nil end end end end