module Mack module ViewHelpers # :nodoc: # A useful collection of helpers for forms. module FormHelpers # Examples: # <% form(users_create_url) do -%> # # form stuff here... # <% end -%> # # <% form(users_update_url, :method => :put) do -%> # # form stuff here... # <% end -%> # # <% form(photos_create_url, :multipart => true) do -%> # # form stuff here... # <% end -%> def form(action, options = {}, &block) options = {:method => :post, :action => action}.merge(options) if options[:id] options = {:class => options[:id]}.merge(options) end if options[:multipart] options = {:enctype => "multipart/form-data"}.merge(options) options.delete(:multipart) end meth = nil unless options[:method] == :get || options[:method] == :post meth = "\n" options[:method] = :post end concat("
", block.binding) # content_tag(:form, options, &block) end # Generates a button with a form around it and will set the request method to delete. def delete_button(url, value = "Delete", form_options = {}, button_options = {}) if button_options[:confirm] button_options[:onclick] = "if (confirm('#{button_options[:confirm]}')) {submit();}; return false;" button_options.delete(:confirm) end t = "\n" << hidden_field(:_method, :value => :delete) t << "\n" << submit_button(value, button_options) t << "\n" content_tag(:form, {:action => url, :method => :post}.merge(form_options), t) end alias_deprecated_method :submit_tag, :submit_button, '0.7.0' # Examples: # <%= submit_button %> # => # <%= submit_button "Login" %> # => def submit_button(value = "Submit", options = {}, *original_args) # non_content_tag(:input, {:type => :submit, :value => value}.merge(options)) content_tag(:button, {:type => :submit}.merge(options), value) end # Examples: # @user = User.new(:accepted_tos => true) # <%= check_box :user, :accepted_tos %> # => # <%= check_box :i_dont_exist %> # => def check_box(name, *args) build_form_element(name, {:type => :checkbox}, *args) do |var, fe, options| if options[:value] options.merge!(:checked => "checked") end options.delete(:value) end end # Examples: # @user = User.new(:bio_file => "~/bio.doc") # <%= file_field :user, :bio_file %> # => # <%= file_field :i_dont_exist %> # => def file_field(name, *args) build_form_element(name, {:type => :file}, *args) end # Examples: # @user = User.new(:email => "mark@mackframework.com") # <%= hidden_field :user, :email %> # => # <%= hidden_field :i_dont_exist %> # => def hidden_field(name, *args) build_form_element(name, {:type => :hidden}, *args) end # Examples: # <%= image_submit "logo.png" %> # => def image_submit(src, options = {}) non_content_tag(:input, {:type => :image, :src => "/images/#{src}"}.merge(options)) end # Examples: # @user = User.new(:level => 1) # <%= select_tag :user, :level, :options => [["one", 1], ["two", 2]] %> # => # <%= select_tag :user :level, :options => {:one => 1, :two => 2} %> # => # <%= select_tag :i_dont_exist :options => [["one", 1], ["two", 2]], :selected => 1 %> # => def select_tag(name, *args) var = instance_variable_get("@#{name}") fe = FormElement.new(*args) options = {:name => name, :id => name} unless fe.calling_method == :to_s options.merge!(:name => "#{name}[#{fe.calling_method}]", :id => "#{name}_#{fe.calling_method}") end content = "" opts = fe.options[:options] unless opts.nil? sopts = opts if opts.is_a?(Array) elsif opts.is_a?(Hash) sopts = [] opts.sort.each do |k,v| sopts << [k, v] end else raise ArgumentError.new(":options must be either an Array of Arrays or a Hash!") end sel_value = var.send(fe.calling_method) if var sel_value = fe.options[:selected] if fe.options[:selected] sopts.each do |kv| selected = kv[1].to_s == sel_value.to_s ? "selected" : "" content << %{\n} end fe.options.delete(:selected) fe.options.delete(:options) end return label_parameter_tag(name, options[:id], var, fe) + content_tag(:select, options.merge(fe.options), content) end # Examples: # @user = User.new(:bio => "my bio here") # <%= text_area :user, :bio %> # => # <%= text_area :i_dont_exist %> # => # <%= text_area :i_dont_exist :value => "hi there" %> # => def text_area(name, *args) var = instance_variable_get("@#{name}") fe = FormElement.new(*args) options = {:name => name, :id => name, :cols => 60, :rows => 20} if var.nil? value = fe.options[:value] fe.options.delete(:value) return label_parameter_tag(name, options[:id], var, fe) + content_tag(:textarea, options.merge(fe.options), value) else unless fe.calling_method == :to_s options.merge!(:name => "#{name}[#{fe.calling_method}]", :id => "#{name}_#{fe.calling_method}") end options[:value] = var.send(fe.calling_method) yield var, fe, options if block_given? content = options[:value] options.delete(:value) return label_parameter_tag(name, options[:id], var, fe) + content_tag(:textarea, options.merge(fe.options), content) end end # Examples: # @user = User.new(:email => "mark@mackframework.com") # <%= text_field :user, :email %> # => # <%= text_field :i_dont_exist %> # => def text_field(name, *args) build_form_element(name, {:type => :text}, *args) end # Examples: # @user = User.new(:email => "mark@mackframework.com") # <%= password_field :user, :email %> # => # <%= password_field :i_dont_exist %> # => def password_field(name, *args) build_form_element(name, {:type => :password}, *args) end # Examples: # @user = User.new(:level => 1) # <%= radio_button :user, :level %> # => # <%= radio_button :user, :level, :value => 2 %> # => # <%= radio_button :i_dont_exist %> # => def radio_button(name, *args) build_form_element(name, {:type => :radio, :value => ""}, *args) do |var, fe, options| if fe.options[:value] if fe.options[:value] == options[:value] options.merge!(:checked => "checked") end elsif options[:value] options.merge!(:checked => "checked") end end end # Examples: # @user = User.new # <%= label_tag :user, :email %> # => # <%= label_tag :i_dont_exist %> # => # <%= label_tag :i_dont_exist, :value => "Hello" %> # => def label_tag(name, *args) fe = FormElement.new(*args) unless fe.options[:for] fe.options[:for] = (fe.calling_method == :to_s ? name.to_s : "#{name}_#{fe.calling_method}") end unless fe.options[:value] fe.options[:value] = (fe.calling_method == :to_s ? name.to_s.humanize : fe.calling_method.to_s.humanize) end content = fe.options[:value] fe.options.delete(:value) content_tag(:label, fe.options, content) end private def label_parameter_tag(name, id, var, fe) label = "" if fe.options[:label] if fe.options[:label].is_a?(TrueClass) if var.nil? label = %{} else label = %{} end else label = %{} end fe.options.delete(:label) end return label end def build_form_element(name, options, *original_args) # :nodoc: var = instance_variable_get("@#{name}") fe = FormElement.new(*original_args) options = {:name => name, :id => name}.merge(options) if var.nil? return label_parameter_tag(name, options[:id], var, fe) + non_content_tag(:input, options.merge(fe.options)) else unless fe.calling_method == :to_s options.merge!(:name => "#{name}[#{fe.calling_method}]", :id => "#{name}_#{fe.calling_method}") end options[:value] = var.send(fe.calling_method) yield var, fe, options if block_given? return label_parameter_tag(name, options[:id], var, fe) + non_content_tag(:input, options.merge(fe.options)) end end class FormElement # :nodoc: attr_accessor :calling_method attr_accessor :options def initialize(*args) args = args.parse_splat_args self.calling_method = :to_s self.options = {} case args when Symbol, String self.calling_method = args when Hash self.options = args when Array self.calling_method = args[0] self.options = args[1] when nil else raise ArgumentError.new("You must provide either a Symbol, a String, a Hash, or a combination thereof.") end if self.options[:checked] self.options[:checked] = :checked end end end end # FormHelpers end # ViewHelpers end # Mack