package com.smartandroid.sa.tag.nodes;
import java.util.ArrayList;
import java.util.List;
import com.smartandroid.sa.tag.Connection;
import com.smartandroid.sa.tag.SmartTag;
import com.smartandroid.sa.tag.helper.HttpConnection;
import com.smartandroid.sa.tag.helper.Validate;
import com.smartandroid.sa.tag.parser.Tag;
import com.smartandroid.sa.tag.select.Elements;
/**
* A HTML Form Element provides ready access to the form fields/controls that
* are associated with it. It also allows a form to easily be submitted.
*/
public class FormElement extends Element {
private final Elements elements = new Elements();
/**
* Create a new, standalone form element.
*
* @param tag
* tag of this element
* @param baseUri
* the base URI
* @param attributes
* initial attributes
*/
public FormElement(Tag tag, String baseUri, Attributes attributes) {
super(tag, baseUri, attributes);
}
/**
* Get the list of form control elements associated with this form.
*
* @return form controls associated with this element.
*/
public Elements elements() {
return elements;
}
/**
* Add a form control element to this form.
*
* @param element
* form control to add
* @return this form element, for chaining
*/
public FormElement addElement(Element element) {
elements.add(element);
return this;
}
/**
* Prepare to submit this form. A Connection object is created with the
* request set up from the form values. You can then set up other options
* (like user-agent, timeout, cookies), then execute it.
*
* @return a connection prepared from the values of this form.
* @throws IllegalArgumentException
* if the form's absolute action URL cannot be determined. Make
* sure you pass the document's base URI when parsing.
*/
public Connection submit() {
String action = hasAttr("action") ? absUrl("action") : baseUri();
Validate.notEmpty(
action,
"Could not determine a form action URL for submit. Ensure you set a base URI when parsing.");
Connection.Method method = attr("method").toUpperCase().equals("POST") ? Connection.Method.POST
: Connection.Method.GET;
Connection con = SmartTag.connect(action).data(formData()).method(method);
return con;
}
/**
* Get the data that this form submits. The returned list is a copy of the
* data, and changes to the contents of the list will not be reflected in
* the DOM.
*
* @return a list of key vals
*/
public List<Connection.KeyVal> formData() {
ArrayList<Connection.KeyVal> data = new ArrayList<Connection.KeyVal>();
// iterate the form control elements and accumulate their values
for (Element el : elements) {
if (!el.tag().isFormSubmittable())
continue; // contents are form listable, superset of submitable
String name = el.attr("name");
if (name.length() == 0)
continue;
if ("select".equals(el.tagName())) {
Elements options = el.select("option[selected]");
for (Element option : options) {
data.add(HttpConnection.KeyVal.create(name, option.val()));
}
} else {
data.add(HttpConnection.KeyVal.create(name, el.val()));
}
}
return data;
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
}