| Class | WWW::Mechanize::GlobalForm |
| In: |
lib/mechanize/form.rb
|
| Parent: | Object |
GlobalForm provides all access to form fields, such as the buttons, check boxes, and text input.
GlobalForm takes two nodes, the node where the form tag is located (form_node), and another node, from which to start looking for form elements (elements_node) like buttons and the like. For class Form both fall together into one and the same node.
Class Form does not work in the case there is some invalid (unbalanced) html involved, such as:
<td>
<form>
</td>
<td>
<input .../>
</form>
</td>
| fields | -> | elements |
| action | [RW] | |
| buttons | [R] | |
| checkboxes | [R] | |
| elements_node | [R] | |
| enctype | [R] | |
| fields | [R] | |
| file_uploads | [R] | |
| form_node | [R] | |
| method | [RW] | |
| name | [RW] | |
| radiobuttons | [R] |
# File lib/mechanize/form.rb, line 32
32: def initialize(form_node, elements_node)
33: @form_node, @elements_node = form_node, elements_node
34:
35: @method = (@form_node['method'] || 'GET').upcase
36: @action = Util::html_unescape(@form_node['action'])
37: @name = @form_node['name']
38: @enctype = @form_node['enctype'] || 'application/x-www-form-urlencoded'
39: @clicked_buttons = []
40:
41: parse
42: end
This method adds a button to the query. If the form needs to be submitted with multiple buttons, pass each button to this method.
# File lib/mechanize/form.rb, line 85
85: def add_button_to_query(button)
86: @clicked_buttons << button
87: end
This method builds an array of arrays that represent the query parameters to be used with this form. The return value can then be used to create a query string for this form.
# File lib/mechanize/form.rb, line 47
47: def build_query(buttons = [])
48: query = []
49:
50: fields().each do |f|
51: query.push(*f.query_value)
52: end
53:
54: checkboxes().each do |f|
55: query.push(*f.query_value) if f.checked
56: end
57:
58: radio_groups = {}
59: radiobuttons().each do |f|
60: radio_groups[f.name] ||= []
61: radio_groups[f.name] << f
62: end
63:
64: # take one radio button from each group
65: radio_groups.each_value do |g|
66: checked = g.select {|f| f.checked}
67:
68: if checked.size == 1
69: f = checked.first
70: query.push(*f.query_value)
71: elsif checked.size > 1
72: raise "multiple radiobuttons are checked in the same group!"
73: end
74: end
75:
76: @clicked_buttons.each { |b|
77: query.push(*b.query_value)
78: }
79:
80: query
81: end
Removes all fields with name field_name.
# File lib/mechanize/form.rb, line 109
109: def delete_field!(field_name)
110: @fields.delete_if{ |f| f.name == field_name}
111: end
This method calculates the request data to be sent back to the server for this form, depending on if this is a regular post, get, or a multi-part post,
# File lib/mechanize/form.rb, line 92
92: def request_data
93: query_params = build_query()
94: case @enctype.downcase
95: when 'multipart/form-data'
96: boundary = rand_string(20)
97: @enctype << "; boundary=#{boundary}"
98: params = []
99: query_params.each { |k,v| params << param_to_multipart(k, v) }
100: @file_uploads.each { |f| params << file_to_multipart(f) }
101: params.collect { |p| "--#{boundary}\r\n#{p}" }.join('') +
102: "--#{boundary}--\r\n"
103: else
104: WWW::Mechanize.build_query_string(query_params)
105: end
106: end
# File lib/mechanize/form.rb, line 178
178: def file_to_multipart(file)
179: file_name = file.file_name ? ::File.basename(file.file_name) : ''
180: body = "Content-Disposition: form-data; name=\"" +
181: "#{mime_value_quote(file.name)}\"; " +
182: "filename=\"#{mime_value_quote(file_name)}\"\r\n" +
183: "Content-Transfer-Encoding: binary\r\n"
184:
185: if file.file_data.nil? and ! file.file_name.nil?
186: file.file_data = ::File.open(file.file_name, "rb") { |f| f.read }
187: file.mime_type = WEBrick::HTTPUtils.mime_type(file.file_name,
188: WEBrick::HTTPUtils::DefaultMimeTypes)
189: end
190:
191: if file.mime_type != nil
192: body << "Content-Type: #{file.mime_type}\r\n"
193: end
194:
195: body <<
196: if file.file_data.respond_to? :read
197: "\r\n#{file.file_data.read}\r\n"
198: else
199: "\r\n#{file.file_data}\r\n"
200: end
201:
202: body
203: end
# File lib/mechanize/form.rb, line 168
168: def mime_value_quote(str)
169: str.gsub(/(["\r\\])/){|s| '\\' + s}
170: end
# File lib/mechanize/form.rb, line 172
172: def param_to_multipart(name, value)
173: return "Content-Disposition: form-data; name=\"" +
174: "#{mime_value_quote(name)}\"\r\n" +
175: "\r\n#{value}\r\n"
176: end
# File lib/mechanize/form.rb, line 114
114: def parse
115: @fields = WWW::Mechanize::List.new
116: @buttons = WWW::Mechanize::List.new
117: @file_uploads = WWW::Mechanize::List.new
118: @radiobuttons = WWW::Mechanize::List.new
119: @checkboxes = WWW::Mechanize::List.new
120:
121: # Find all input tags
122: (@elements_node/'input').each do |node|
123: type = (node['type'] || 'text').downcase
124: name = node['name']
125: next if name.nil? && !(type == 'submit' || type =='button')
126: case type
127: when 'text', 'password', 'hidden', 'int'
128: @fields << Field.new(node['name'], node['value'] || '')
129: when 'radio'
130: @radiobuttons << RadioButton.new(node['name'], node['value'], node.has_attribute?('checked'), self)
131: when 'checkbox'
132: @checkboxes << CheckBox.new(node['name'], node['value'], node.has_attribute?('checked'), self)
133: when 'file'
134: @file_uploads << FileUpload.new(node['name'], nil)
135: when 'submit'
136: @buttons << Button.new(node['name'], node['value'])
137: when 'button'
138: @buttons << Button.new(node['name'], node['value'])
139: when 'image'
140: @buttons << ImageButton.new(node['name'], node['value'])
141: end
142: end
143:
144: # Find all textarea tags
145: (@elements_node/'textarea').each do |node|
146: next if node['name'].nil?
147: @fields << Field.new(node['name'], node.inner_text)
148: end
149:
150: # Find all select tags
151: (@elements_node/'select').each do |node|
152: next if node['name'].nil?
153: if node.has_attribute? 'multiple'
154: @fields << MultiSelectList.new(node['name'], node)
155: else
156: @fields << SelectList.new(node['name'], node)
157: end
158: end
159: end