/*
GNU LESSER GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
/*
* Created on Jan 14, 2006
*/
package org.lobobrowser.html.domimpl;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import org.lobobrowser.html.FormInput;
import org.lobobrowser.html.HtmlRendererContext;
import org.lobobrowser.html.js.Executor;
import org.lobobrowser.html.js.Window;
import org.lobobrowser.html.js.Window.JSSupplierTask;
import org.mozilla.javascript.Function;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.html.HTMLCollection;
import org.w3c.dom.html.HTMLFormElement;
public class HTMLFormElementImpl extends HTMLAbstractUIElement implements HTMLFormElement {
public HTMLFormElementImpl(final String name) {
super(name);
}
public HTMLFormElementImpl() {
super("FORM");
}
public Object namedItem(final String name) {
try {
// TODO: This could use document.namedItem.
this.visit(new NodeVisitor() {
public void visit(final Node node) {
if (HTMLFormElementImpl.isInput(node)) {
if (name.equals(((Element) node).getAttribute("name"))) {
throw new StopVisitorException(node);
}
}
}
});
} catch (final StopVisitorException sve) {
return sve.getTag();
}
return null;
}
public Object item(final int index) {
try {
this.visit(new NodeVisitor() {
private int current = 0;
public void visit(final Node node) {
if (HTMLFormElementImpl.isInput(node)) {
if (this.current == index) {
throw new StopVisitorException(node);
}
this.current++;
}
}
});
} catch (final StopVisitorException sve) {
return sve.getTag();
}
return null;
}
private HTMLCollection elements;
public HTMLCollection getElements() {
HTMLCollection elements = this.elements;
if (elements == null) {
elements = new DescendentHTMLCollection(this, new InputFilter(), this.treeLock, false);
this.elements = elements;
}
return elements;
}
public int getLength() {
return this.getElements().getLength();
}
public String getName() {
return this.getAttribute("name");
}
public void setName(final String name) {
this.setAttribute("name", name);
}
public String getAcceptCharset() {
return this.getAttribute("acceptCharset");
}
public void setAcceptCharset(final String acceptCharset) {
this.setAttribute("acceptCharset", acceptCharset);
}
public String getAction() {
return this.getAttribute("action");
}
public void setAction(final String action) {
this.setAttribute("action", action);
}
public String getEnctype() {
return this.getAttribute("enctype");
}
public void setEnctype(final String enctype) {
this.setAttribute("enctype", enctype);
}
public String getMethod() {
String method = this.getAttribute("method");
if (method == null) {
method = "GET";
}
return method;
}
public void setMethod(final String method) {
this.setAttribute("method", method);
}
public String getTarget() {
return this.getAttribute("target");
}
public void setTarget(final String target) {
this.setAttribute("target", target);
}
public void submit() {
this.submit(null);
}
private Function onsubmit;
public void setOnsubmit(final Function value) {
this.onsubmit = value;
}
public Function getOnsubmit() {
return this.getEventFunction(this.onsubmit, "onsubmit");
}
/**
* This method should be called when form submission is done by a submit
* button.
*
* @param extraFormInputs
* Any additional form inputs that need to be submitted, e.g. the
* submit button parameter.
*/
public final void submit(final FormInput[] extraFormInputs) {
final Function onsubmit = this.getOnsubmit();
if (onsubmit != null) {
// TODO: onsubmit event object?
// dispatchEvent(new Event("submit", this));
final Window window = ((HTMLDocumentImpl) document).getWindow();
window.addJSTask(new JSSupplierTask<>(0, () -> {
return Executor.executeFunction(this, onsubmit, null, window.getContextFactory());
}, (result) -> {
if (result) {
submitFormImpl(extraFormInputs);
}
}));
} else {
submitFormImpl(extraFormInputs);
}
}
private void submitFormImpl(final FormInput[] extraFormInputs) {
final HtmlRendererContext context = this.getHtmlRendererContext();
if (context != null) {
final ArrayList<FormInput> formInputs = new ArrayList<>();
if (extraFormInputs != null) {
for (final FormInput extraFormInput : extraFormInputs) {
formInputs.add(extraFormInput);
}
}
this.visit(new NodeVisitor() {
public void visit(final Node node) {
if (node instanceof HTMLElementImpl) {
final FormInput[] fis = ((HTMLElementImpl) node).getFormInputs();
if (fis != null) {
for (final FormInput fi : fis) {
if (fi.getName() == null) {
throw new IllegalStateException("Form input does not have a name: " + node);
}
formInputs.add(fi);
}
}
}
}
});
final FormInput[] fia = formInputs.toArray(FormInput.EMPTY_ARRAY);
String href = this.getAction();
if (href == null) {
href = this.getBaseURI();
}
try {
final URL url = this.getFullURL(href);
context.submitForm(this.getMethod(), url, this.getTarget(), this.getEnctype(), fia);
} catch (final MalformedURLException mfu) {
this.warn("submit()", mfu);
}
}
}
public void reset() {
this.visit(new NodeVisitor() {
public void visit(final Node node) {
if (node instanceof HTMLBaseInputElement) {
((HTMLBaseInputElement) node).resetInput();
}
}
});
}
static boolean isInput(final Node node) {
final String name = node.getNodeName().toLowerCase();
return name.equals("input") || name.equals("textarea") || name.equals("select");
}
private class InputFilter implements NodeFilter {
/*
* (non-Javadoc)
*
* @see org.xamjwg.html.domimpl.NodeFilter#accept(org.w3c.dom.Node)
*/
public boolean accept(final Node node) {
return HTMLFormElementImpl.isInput(node);
}
}
}