HtmlFormElement
sealed class HtmlFormElement : HtmlElement, IHtmlFormElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle, IGlobalEventHandlers
Represents the form element.
using AngleSharp.Dom.Collections;
using AngleSharp.Dom.Css;
using AngleSharp.Dom.Events;
using AngleSharp.Extensions;
using AngleSharp.Html;
using AngleSharp.Network;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace AngleSharp.Dom.Html
{
internal sealed class HtmlFormElement : HtmlElement, IHtmlFormElement, IHtmlElement, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode, IElementCssInlineStyle, IGlobalEventHandlers
{
private HtmlFormControlsCollection _elements;
public IElement this[int index] {
get {
return Elements[index];
}
}
public IElement this[string name] {
get {
return Elements[name];
}
}
public string Name {
get {
return this.GetOwnAttribute(AttributeNames.Name);
}
set {
this.SetOwnAttribute(AttributeNames.Name, value, false);
}
}
public int Length => Elements.Length;
public HtmlFormControlsCollection Elements => _elements ?? (_elements = new HtmlFormControlsCollection(this, null));
IHtmlFormControlsCollection IHtmlFormElement.Elements {
get {
return Elements;
}
}
public string AcceptCharset {
get {
return this.GetOwnAttribute(AttributeNames.AcceptCharset);
}
set {
this.SetOwnAttribute(AttributeNames.AcceptCharset, value, false);
}
}
public string Action {
get {
return this.GetOwnAttribute(AttributeNames.Action);
}
set {
this.SetOwnAttribute(AttributeNames.Action, value, false);
}
}
public string Autocomplete {
get {
return this.GetOwnAttribute(AttributeNames.AutoComplete);
}
set {
this.SetOwnAttribute(AttributeNames.AutoComplete, value, false);
}
}
public string Enctype {
get {
return this.GetOwnAttribute(AttributeNames.Enctype).ToEncodingType();
}
set {
this.SetOwnAttribute(AttributeNames.Enctype, value.ToEncodingType(), false);
}
}
public string Encoding {
get {
return Enctype;
}
set {
Enctype = value;
}
}
public string Method {
get {
return this.GetOwnAttribute(AttributeNames.Method) ?? string.Empty;
}
set {
this.SetOwnAttribute(AttributeNames.Method, value, false);
}
}
public bool NoValidate {
get {
return this.GetBoolAttribute(AttributeNames.NoValidate);
}
set {
this.SetBoolAttribute(AttributeNames.NoValidate, value);
}
}
public string Target {
get {
return this.GetOwnAttribute(AttributeNames.Target);
}
set {
this.SetOwnAttribute(AttributeNames.Target, value, false);
}
}
public HtmlFormElement(Document owner, string prefix = null)
: base(owner, TagNames.Form, prefix, NodeFlags.Special)
{
}
public Task<IDocument> SubmitAsync()
{
DocumentRequest submission = GetSubmission();
return this.NavigateToAsync(submission);
}
public Task<IDocument> SubmitAsync(IHtmlElement sourceElement)
{
DocumentRequest submission = GetSubmission(sourceElement);
return this.NavigateToAsync(submission);
}
public DocumentRequest GetSubmission()
{
return SubmitForm(this, true);
}
public DocumentRequest GetSubmission(IHtmlElement sourceElement)
{
return SubmitForm(sourceElement ?? this, false);
}
public void Reset()
{
foreach (HtmlFormControlElement element in Elements) {
element.Reset();
}
}
public bool CheckValidity()
{
IEnumerable<HtmlFormControlElement> invalidControls = GetInvalidControls();
bool result = true;
foreach (HtmlFormControlElement item in invalidControls) {
if (!item.FireSimpleEvent(EventNames.Invalid, false, true))
result = false;
}
return result;
}
private IEnumerable<HtmlFormControlElement> GetInvalidControls()
{
foreach (HtmlFormControlElement element in Elements) {
if (element.WillValidate && !element.CheckValidity())
yield return element;
}
}
public bool ReportValidity()
{
IEnumerable<HtmlFormControlElement> invalidControls = GetInvalidControls();
bool result = true;
bool flag = false;
foreach (HtmlFormControlElement item in invalidControls) {
if (!item.FireSimpleEvent(EventNames.Invalid, false, true)) {
if (!flag) {
item.DoFocus();
flag = true;
}
result = false;
}
}
return result;
}
public void RequestAutocomplete()
{
}
private DocumentRequest SubmitForm(IHtmlElement from, bool submittedFromSubmitMethod)
{
Document owner = base.Owner;
if ((owner.ActiveSandboxing & Sandboxes.Forms) != Sandboxes.Forms) {
if (submittedFromSubmitMethod || from.HasAttribute(AttributeNames.FormNoValidate) || NoValidate || CheckValidity()) {
Url url = string.IsNullOrEmpty(Action) ? new Url(owner.DocumentUri) : this.HyperReference(Action);
bool flag = false;
IBrowsingContext context = owner.Context;
string target = Target;
DocumentReadyState readyState = owner.ReadyState;
if (!string.IsNullOrEmpty(target))
flag = (owner.GetTarget(target) == null);
if (flag)
owner.CreateTarget(target);
string scheme = url.Scheme;
HttpMethod method = Method.ToEnum(HttpMethod.Get);
return SubmitForm(method, scheme, url, from);
}
this.FireSimpleEvent(EventNames.Invalid, false, false);
}
return null;
}
private DocumentRequest SubmitForm(HttpMethod method, string scheme, Url action, IHtmlElement submitter)
{
if (scheme.IsOneOf(ProtocolNames.Http, ProtocolNames.Https)) {
switch (method) {
case HttpMethod.Get:
return MutateActionUrl(action, submitter);
case HttpMethod.Post:
return SubmitAsEntityBody(action, submitter);
}
} else if (scheme.Is(ProtocolNames.Data)) {
switch (method) {
case HttpMethod.Get:
return GetActionUrl(action);
case HttpMethod.Post:
return PostToData(action, submitter);
}
} else if (scheme.Is(ProtocolNames.Mailto)) {
switch (method) {
case HttpMethod.Get:
return MailWithHeaders(action, submitter);
case HttpMethod.Post:
return MailAsBody(action, submitter);
}
} else if (scheme.IsOneOf(ProtocolNames.Ftp, ProtocolNames.JavaScript)) {
return GetActionUrl(action);
}
return MutateActionUrl(action, submitter);
}
private DocumentRequest PostToData(Url action, IHtmlElement submitter)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(submitter);
string enctype = Enctype;
string s = string.Empty;
using (StreamReader streamReader = new StreamReader(formDataSet.CreateBody(enctype, charset)))
s = streamReader.ReadToEnd();
if (action.Href.Contains("%%%%")) {
s = TextEncoding.UsAscii.GetBytes(s).UrlEncode();
action.Href = action.Href.ReplaceFirst("%%%%", s);
} else if (action.Href.Contains("%%")) {
s = TextEncoding.Utf8.GetBytes(s).UrlEncode();
action.Href = action.Href.ReplaceFirst("%%", s);
}
return GetActionUrl(action);
}
private DocumentRequest MailWithHeaders(Url action, IHtmlElement submitter)
{
Stream stream = ConstructDataSet(submitter).AsUrlEncoded(TextEncoding.UsAscii);
string text = string.Empty;
using (StreamReader streamReader = new StreamReader(stream))
text = streamReader.ReadToEnd();
action.Query = text.Replace("+", "%20");
return GetActionUrl(action);
}
private DocumentRequest MailAsBody(Url action, IHtmlElement submitter)
{
FormDataSet formDataSet = ConstructDataSet(submitter);
string enctype = Enctype;
Encoding usAscii = TextEncoding.UsAscii;
Stream stream = formDataSet.CreateBody(enctype, usAscii);
string s = string.Empty;
using (StreamReader streamReader = new StreamReader(stream))
s = streamReader.ReadToEnd();
action.Query = "body=" + usAscii.GetBytes(s).UrlEncode();
return GetActionUrl(action);
}
private DocumentRequest GetActionUrl(Url action)
{
return DocumentRequest.Get(action, this, base.Owner.DocumentUri);
}
private DocumentRequest SubmitAsEntityBody(Url target, IHtmlElement submitter)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(submitter);
string text = Enctype;
Stream body = formDataSet.CreateBody(text, charset);
if (text.Isi(MimeTypeNames.MultipartForm))
text = MimeTypeNames.MultipartForm + "; boundary=" + formDataSet.Boundary;
return DocumentRequest.Post(target, body, text, this, base.Owner.DocumentUri);
}
private DocumentRequest MutateActionUrl(Url action, IHtmlElement submitter)
{
string charset = string.IsNullOrEmpty(AcceptCharset) ? base.Owner.CharacterSet : AcceptCharset;
FormDataSet formDataSet = ConstructDataSet(submitter);
Encoding encoding = TextEncoding.Resolve(charset);
using (StreamReader streamReader = new StreamReader(formDataSet.AsUrlEncoded(encoding)))
action.Query = streamReader.ReadToEnd();
return GetActionUrl(action);
}
private FormDataSet ConstructDataSet(IHtmlElement submitter)
{
FormDataSet formDataSet = new FormDataSet();
foreach (HtmlFormControlElement element in this.GetElements<HtmlFormControlElement>(true, null)) {
if (!element.IsDisabled && !(element.ParentElement is IHtmlDataListElement) && element.Form == this)
element.ConstructDataSet(formDataSet, submitter);
}
return formDataSet;
}
}
}