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); } }