class WWW::Mechanize::Form

puts form[‘name’]<br>form = ‘Aaron’
Set the input field ‘name’ to “Aaron”
form.fields.each { |f| puts f.name }
form = page.forms.first # => WWW::Mechanize::Form
Find a form and print out its fields
==Example
See GlobalForm for more methods.
of input fields available in a form can be accessed through this object.
This class encapsulates a form parsed out of an HTML page. Each type
=Synopsis

def [](field_name)

puts form['name']
Fetch the value set in the input field 'name'
==Example
Fetch the value of the first input field with the name passed in
def [](field_name)
  f = field(field_name)
  f && f.value
end

def []=(field_name, value)

form['name'] = 'Aaron'
Set the value in the input field 'name' to "Aaron"
==Example
Set the value of the first input field with the name passed in
def []=(field_name, value)
  f = field(field_name)
  if f.nil?
    add_field!(field_name, value)
  else
    f.value = value
  end
end

def add_button_to_query(button)

submitted with multiple buttons, pass each button to this method.
This method adds a button to the query. If the form needs to be
def add_button_to_query(button)
  @clicked_buttons << button
end

def add_field!(field_name, value = nil)

Add a field with +field_name+ and +value+
def add_field!(field_name, value = nil)
  fields << Field.new(field_name, value)
end

def build_query(buttons = [])

be used to create a query string for this form.
parameters to be used with this form. The return value can then
This method builds an array of arrays that represent the query
def build_query(buttons = [])
  query = []
  fields().each do |f|
    query.push(*f.query_value)
  end
  checkboxes().each do |f|
    query.push(*f.query_value) if f.checked
  end
  radio_groups = {}
  radiobuttons().each do |f|
    radio_groups[f.name] ||= []
    radio_groups[f.name] << f 
  end
  # take one radio button from each group
  radio_groups.each_value do |g|
    checked = g.select {|f| f.checked}
    if checked.size == 1
      f = checked.first
      query.push(*f.query_value)
    elsif checked.size > 1 
      raise "multiple radiobuttons are checked in the same group!" 
    end
  end
  @clicked_buttons.each { |b|
    query.push(*b.query_value)
  }
  query
end

def click_button(button = buttons.first)

to the first button.
Submit form using +button+. Defaults
def click_button(button = buttons.first)
  submit(button)
end

def delete_field!(field_name)

Removes all fields with name +field_name+.
def delete_field!(field_name)
  @fields.delete_if{ |f| f.name == field_name}
end

def file_to_multipart(file)

def file_to_multipart(file)
  file_name = file.file_name ? ::File.basename(file.file_name) : ''
  body =  "Content-Disposition: form-data; name=\"" +
          "#{mime_value_quote(file.name)}\"; " +
          "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
          "Content-Transfer-Encoding: binary\r\n"
  if file.file_data.nil? and ! file.file_name.nil?
    file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
    file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
                                    WEBrick::HTTPUtils::DefaultMimeTypes)
  end
  if file.mime_type != nil
    body << "Content-Type: #{file.mime_type}\r\n"
  end
  body <<
    if file.file_data.respond_to? :read
      "\r\n#{file.file_data.read}\r\n"
    else
      "\r\n#{file.file_data}\r\n"
    end
  body
end

def has_field?(field_name)

Returns whether or not the form contains a field with +field_name+
def has_field?(field_name)
  ! fields.find { |f| f.name.eql? field_name }.nil?
end

def has_value?(value)

def has_value?(value)
  ! fields.find { |f| f.value.eql? value }.nil?
end

def initialize(node, mech=nil, page=nil)

def initialize(node, mech=nil, page=nil)
  @enctype = node['enctype'] || 'application/x-www-form-urlencoded'
  @form_node        = node
  @action           = Util.html_unescape(node['action'])
  @method           = (node['method'] || 'GET').upcase
  @name             = node['name']
  @clicked_buttons  = []
  @page             = page
  @mech             = mech
  parse
end

def keys; fields.map { |f| f.name }; end

def keys; fields.map { |f| f.name }; end

def method_missing(id,*args)

Treat form fields like accessors.
def method_missing(id,*args)
  method = id.to_s.gsub(/=$/, '')
  if field(method)
    return field(method).value if args.empty?
    return field(method).value = args[0]
  end
  super
end

def mime_value_quote(str)

def mime_value_quote(str)
  str.gsub(/(["\r\\])/){|s| '\\' + s}
end

def param_to_multipart(name, value)

def param_to_multipart(name, value)
  return "Content-Disposition: form-data; name=\"" +
          "#{mime_value_quote(name)}\"\r\n" +
          "\r\n#{value}\r\n"
end

def parse

def parse
  @fields       = WWW::Mechanize::List.new
  @buttons      = WWW::Mechanize::List.new
  @file_uploads = WWW::Mechanize::List.new
  @radiobuttons = WWW::Mechanize::List.new
  @checkboxes   = WWW::Mechanize::List.new
  # Find all input tags
  form_node.search('input').each do |node|
    type = (node['type'] || 'text').downcase
    name = node['name']
    next if name.nil? && !(type == 'submit' || type =='button')
    case type
    when 'radio'
      @radiobuttons << RadioButton.new(node['name'], node['value'], !!node['checked'], self)
    when 'checkbox'
      @checkboxes << CheckBox.new(node['name'], node['value'], !!node['checked'], self)
    when 'file'
      @file_uploads << FileUpload.new(node['name'], nil) 
    when 'submit'
      @buttons << Button.new(node['name'], node['value'])
    when 'button'
      @buttons << Button.new(node['name'], node['value'])
    when 'image'
      @buttons << ImageButton.new(node['name'], node['value'])
    else
      @fields << Field.new(node['name'], node['value'] || '') 
    end
  end
  # Find all textarea tags
  form_node.search('textarea').each do |node|
    next if node['name'].nil?
    @fields << Field.new(node['name'], node.inner_text)
  end
  # Find all select tags
  form_node.search('select').each do |node|
    next if node['name'].nil?
    if node.has_attribute? 'multiple'
      @fields << MultiSelectList.new(node['name'], node)
    else
      @fields << SelectList.new(node['name'], node)
    end
  end
  # Find all submit button tags
  # FIXME: what can I do with the reset buttons?
  form_node.search('button').each do |node|
    type = (node['type'] || 'submit').downcase
    next if type == 'reset'
    @buttons << Button.new(node['name'], node['value'])
  end
end

def pretty_print(q)

def pretty_print(q)
  q.object_group(self) {
    q.breakable; q.group(1, '{name', '}') { q.breakable; q.pp name }
    q.breakable; q.group(1, '{method', '}') { q.breakable; q.pp method }
    q.breakable; q.group(1, '{action', '}') { q.breakable; q.pp action }
    q.breakable; q.group(1, '{fields', '}') {
      fields.each do |field|
        q.breakable
        q.pp field
      end
    }
    q.breakable; q.group(1, '{radiobuttons', '}') {
      radiobuttons.each { |b| q.breakable; q.pp b }
    }
    q.breakable; q.group(1, '{checkboxes', '}') {
      checkboxes.each { |b| q.breakable; q.pp b }
    }
    q.breakable; q.group(1, '{file_uploads', '}') {
      file_uploads.each { |b| q.breakable; q.pp b }
    }
    q.breakable; q.group(1, '{buttons', '}') {
      buttons.each { |b| q.breakable; q.pp b }
    }
  }
end

def rand_string(len = 10)

def rand_string(len = 10)
  chars = ("a".."z").to_a + ("A".."Z").to_a
  string = ""
  1.upto(len) { |i| string << chars[rand(chars.size-1)] }
  string
end

def request_data

multi-part post,
for this form, depending on if this is a regular post, get, or a
This method calculates the request data to be sent back to the server
def request_data
  query_params = build_query()
  case @enctype.downcase
  when /^multipart\/form-data/
    boundary = rand_string(20)
    @enctype = "multipart/form-data; boundary=#{boundary}"
    params = []
    query_params.each { |k,v| params << param_to_multipart(k, v) }
    @file_uploads.each { |f| params << file_to_multipart(f) }
    params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
      "--#{boundary}--\r\n"
  else
    WWW::Mechanize::Util.build_query_string(query_params)
  end
end

def set_fields(fields = {})

form.set_fields( :foo => { 1 => 'bar' } )
could do the following:
is zero based. For example, to set the second field named 'foo', you
the key as the index in to the form. The index
set the value of a duplicate field, use a value which is a Hash with
same name, this method will set the first one found. If you want to
name, value pairs. If there is more than one field found with the
This method sets multiple fields on the form. It takes a list of field
def set_fields(fields = {})
  fields.each do |k,v|
    case v
    when Hash
      v.each do |index, value|
        self.fields_with(:name => k.to_s).[](index).value = value
      end
    else
      value = nil
      index = 0
      [v].flatten.each do |val|
        index = val.to_i unless value.nil?
        value = val if value.nil?
      end
      self.fields_with(:name => k.to_s).[](index).value = value
    end
  end
end

def submit(button=nil)

Submit this form with the button passed in
def submit(button=nil)
  @mech.submit(self, button)
end

def values; fields.map { |f| f.value }; end

def values; fields.map { |f| f.value }; end