module Padrino::Helpers::FormHelpers

def button_tag(caption, options = {})

button_tag "Cancel", :class => 'clear'
Constructs a button input from the given options
def button_tag(caption, options = {})
  options.reverse_merge!(:value => caption)
  input_tag(:button, options)
end

def check_box_tag(name, options={})

check_box_tag :remember_me, :value => 'Yes'
Constructs a check_box from the given options
def check_box_tag(name, options={})
  options.reverse_merge!(:name => name, :value => '1')
  input_tag(:checkbox, options)
end

def configured_form_builder_class(explicit_builder=nil)

configured_form_builder_class(nil) => StandardFormBuilder
If explicitly defined, returns that, otherwise returns defaults
Returns the FormBuilder class to use based on all available setting sources
def configured_form_builder_class(explicit_builder=nil)
  default_builder = self.respond_to?(:options) && self.options.default_builder
  configured_builder = explicit_builder || default_builder || 'StandardFormBuilder'
  configured_builder = "Padrino::Helpers::FormBuilder::#{configured_builder}".constantize if configured_builder.is_a?(String)
  configured_builder
end

def error_messages_for(*params)

error_messages_for :user
Constructs list html for the errors for a given symbol
def error_messages_for(*params)
  options = params.extract_options!.symbolize_keys
  objects = params.collect {|object_name| object_name.is_a?(Symbol) ? instance_variable_get("@#{object_name}") : object_name }.compact
  count   = objects.inject(0) {|sum, object| sum + object.errors.count }
  unless count.zero?
    html = {}
    [:id, :class].each do |key|
      if options.include?(key)
        value = options[key]
        html[key] = value unless value.blank?
      else
        html[key] = 'field-errors'
      end
    end
    options[:object_name] ||= params.first.class
    I18n.with_options :locale => options[:locale], :scope => [:models, :errors, :template] do |locale|
      header_message = if options.include?(:header_message)
        options[:header_message]
      else
        object_name = options[:object_name].to_s.gsub('_', ' ')
        object_name = I18n.t(object_name, :default => object_name, :scope => :models, :count => 1)
        locale.t :header, :count => count, :model => object_name
      end
      message = options.include?(:message) ? options[:message] : locale.t(:body)
      error_messages = objects.map {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }.join
      contents = ''
      contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
      contents << content_tag(:p, message) unless message.blank?
      contents << content_tag(:ul, error_messages)
      content_tag(:div, contents, html)
    end
  else
    ''
  end
end

def field_set_tag(*args, &block)

parameters: legend_text=nil, options={}
field_set_tag("Office", :class => 'office-set')
Constructs a field_set to group fields with given options
def field_set_tag(*args, &block)
  options = args.extract_options!
  legend_text = args[0].is_a?(String) ? args.first : nil
  legend_html = legend_text.blank? ? '' : content_tag(:legend, legend_text)
  field_set_content = legend_html + capture_html(&block)
  concat_content content_tag('fieldset', field_set_content, options)
end

def fields_for(object, settings={}, &block)

fields_for :assignment do |assigment| ... end
fields_for @user.assignment do |assignment| ... end
Used within an existing form to allow alternate objects within one form
Constructs form fields for an object using given or default form_builder
def fields_for(object, settings={}, &block)
  builder_class = configured_form_builder_class(settings[:builder])
  fields_html = capture_html(builder_class.new(self, object), &block)
  concat_content fields_html
end

def file_field_tag(name, options={})

file_field_tag :photo, :class => 'long'
Constructs a file field input from the given options
def file_field_tag(name, options={})
  options.reverse_merge!(:name => name)
  input_tag(:file, options)
end

def form_for(object, url, settings={}, &block)

form_for @user, '/register', :id => 'register' do |f| ... end
form_for :user, '/register' do |f| ... end
Constructs a form for object using given or default form_builder
def form_for(object, url, settings={}, &block)
  builder_class = configured_form_builder_class(settings[:builder])
  form_html = capture_html(builder_class.new(self, object), &block)
  form_tag(url, settings) { form_html }
end

def form_tag(url, options={}, &block)

form_tag '/register' do ... end
Constructs a form without object based on options
def form_tag(url, options={}, &block)
  options.reverse_merge!(:method => 'post', :action => url)
  options[:enctype] = "multipart/form-data" if options.delete(:multipart)
  options["data-remote"] = "true" if options.delete(:remote)
  inner_form_html = hidden_form_method_field(options[:method]) + capture_html(&block)
  concat_content content_tag('form', inner_form_html, options)
end

def hidden_field_tag(name, options={})

hidden_field_tag :session_key, :value => "__secret__"
Constructs a hidden field input from the given options
def hidden_field_tag(name, options={})
  options.reverse_merge!(:name => name)
  input_tag(:hidden, options)
end

def hidden_form_method_field(desired_method)

hidden_form_method_field('delete') =>
'put' and 'delete' are just specified using hidden fields with form action still 'put'.
Only 'get' and 'post' are allowed within browsers;
returns the hidden method field for 'put' and 'delete' forms
def hidden_form_method_field(desired_method)
  return '' if (desired_method.to_s =~ /get|post/)
  original_method = desired_method.to_s.dup
  desired_method.to_s.replace('post')
  hidden_field_tag(:_method, :value => original_method)
end

def image_submit_tag(source, options={})

submit_tag "Create", :class => 'success'
Constructs a submit button from the given options
def image_submit_tag(source, options={})
  options.reverse_merge!(:src => image_path(source))
  input_tag(:image, options)
end

def label_tag(name, options={}, &block)

label_tag :username, :class => 'long-label' do ... end
label_tag :username, :class => 'long-label'
Constructs a label tag from the given options
def label_tag(name, options={}, &block)
  options.reverse_merge!(:caption => "#{name.to_s.titleize}: ", :for => name)
  caption_text = options.delete(:caption)
  if block_given? # label with inner content
    label_content = caption_text + capture_html(&block)
    concat_content(content_tag(:label, label_content, options))
  else # regular label
    content_tag(:label, caption_text, options)
  end
end

def options_for_select(option_items, selected_value=nil)

Returns the options tags for a select based on the given option items
def options_for_select(option_items, selected_value=nil)
  return '' if option_items.blank?
  option_items.collect do |caption, value|
    value ||= caption
    content_tag(:option, caption, :value => value, :selected => selected_value.to_s =~ /#{value}|#{caption}/)
  end
end

def options_from_collection(collection, fields)

fields is an array containing the fields to display from each item in the collection
Returns an array of option items for a select field based on the given collection
def options_from_collection(collection, fields)
  return '' if collection.blank?
  collection.collect { |item| [ item.send(fields.first), item.send(fields.last) ] }
end

def password_field_tag(name, options={})

password_field_tag :password, :class => 'long'
Constructs a password field input from the given options
def password_field_tag(name, options={})
  options.reverse_merge!(:name => name)
  input_tag(:password, options)
end

def radio_button_tag(name, options={})

radio_button_tag :remember_me, :value => 'true'
Constructs a radio_button from the given options
def radio_button_tag(name, options={})
  options.reverse_merge!(:name => name)
  input_tag(:radio, options)
end

def select_tag(name, options={})

select_tag(:country, :collection => @countries, :fields => [:name, :code])
select_tag(:favorite_color, :options => ['red', 'yellow'], :selected => 'green1')
options = ['option', 'red', 'yellow' ]
options = [['caption', 'value'], ['Green', 'green1'], ['Blue', 'blue1'], ['Black', "black1"]]
Constructs a check_box from the given options
def select_tag(name, options={})
  options.reverse_merge!(:name => name)
  collection, fields = options.delete(:collection), options.delete(:fields)
  options[:options] = options_from_collection(collection, fields) if collection
  options[:options].unshift('') if options.delete(:include_blank)
  select_options_html = options_for_select(options.delete(:options), options.delete(:selected))
  options.merge!(:name => "#{options[:name]}[]") if options[:multiple]
  content_tag(:select, select_options_html, options)
end

def submit_tag(caption="Submit", options={})

submit_tag "Create", :class => 'success'
Constructs a submit button from the given options
def submit_tag(caption="Submit", options={})
  options.reverse_merge!(:value => caption)
  input_tag(:submit, options)
end

def text_area_tag(name, options={})

text_area_tag :username, :class => 'long', :value => "Demo?"
Constructs a text area input from the given options
def text_area_tag(name, options={})
  options.reverse_merge!(:name => name)
  content_tag(:textarea, options.delete(:value).to_s, options)
end

def text_field_tag(name, options={})

text_field_tag :username, :class => 'long'
Constructs a text field input from the given options
def text_field_tag(name, options={})
  options.reverse_merge!(:name => name)
  input_tag(:text, options)
end