CssSelectorConstructor
Class for construction for CSS selectors as specified in
http://www.w3.org/html/wg/drafts/html/master/selectors.html.
using AngleSharp.DOM;
using AngleSharp.DOM.Css;
using AngleSharp.DOM.Html;
using System;
using System.Diagnostics;
namespace AngleSharp.Parser.Css
{
[DebuggerStepThrough]
internal sealed class CssSelectorConstructor
{
private enum State
{
Data,
Attribute,
AttributeOperator,
AttributeValue,
AttributeEnd,
Class,
PseudoClass,
PseudoClassFunction,
PseudoClassFunctionEnd,
PseudoElement
}
private abstract class NthChildSelector
{
public int step;
public int offset;
public Priority Specifity => Priority.OneClass;
}
private sealed class NthFirstChildSelector : NthChildSelector, ISelector, ICssObject
{
public bool Match(IElement element)
{
INode parent = element.Parent;
if (parent == null)
return false;
int num = 1;
for (int i = 0; i < parent.ChildNodes.Length; i++) {
if (parent.ChildNodes[i] == element) {
if (step != 0)
return (num - offset) % step == 0;
return num == offset;
}
if (parent.ChildNodes[i] is IElement)
num++;
}
return true;
}
public string ToCss()
{
return string.Format(":{0}({1}n+{2})", new object[3] {
"nth-child",
step,
offset
});
}
}
private sealed class NthLastChildSelector : NthChildSelector, ISelector, ICssObject
{
public bool Match(IElement element)
{
IElement parentElement = element.ParentElement;
if (parentElement == null)
return false;
int num = 1;
for (int num2 = parentElement.ChildNodes.Length - 1; num2 >= 0; num2--) {
if (parentElement.ChildNodes[num2] == element) {
if (step != 0)
return (num - offset) % step == 0;
return num == offset;
}
if (parentElement.ChildNodes[num2] is IElement)
num++;
}
return true;
}
public string ToCss()
{
return string.Format(":{0}({1}n+{2})", new object[3] {
"nth-last-child",
step,
offset
});
}
}
private sealed class FirstChildSelector : ISelector, ICssObject
{
private static FirstChildSelector instance;
public static FirstChildSelector Instance => instance ?? (instance = new FirstChildSelector());
public Priority Specifity => Priority.OneClass;
private FirstChildSelector()
{
}
public bool Match(IElement element)
{
INode parent = element.Parent;
if (parent == null)
return false;
for (int i = 0; i <= parent.ChildNodes.Length; i++) {
if (parent.ChildNodes[i] == element)
return true;
if (parent.ChildNodes[i] is IElement)
return false;
}
return false;
}
public string ToCss()
{
return ":first-child";
}
}
private sealed class LastChildSelector : ISelector, ICssObject
{
private static LastChildSelector instance;
public static LastChildSelector Instance => instance ?? (instance = new LastChildSelector());
public Priority Specifity => Priority.OneClass;
private LastChildSelector()
{
}
public bool Match(IElement element)
{
IElement parentElement = element.ParentElement;
if (parentElement == null)
return false;
for (int num = parentElement.ChildNodes.Length - 1; num >= 0; num--) {
if (parentElement.ChildNodes[num] == element)
return true;
if (parentElement.ChildNodes[num] is IElement)
return false;
}
return false;
}
public string ToCss()
{
return ":last-child";
}
}
private const string pseudoClassRoot = "root";
private const string pseudoClassFirstOfType = "first-of-type";
private const string pseudoClassLastOfType = "last-of-type";
private const string pseudoClassOnlyChild = "only-child";
private const string pseudoClassFirstChild = "first-child";
private const string pseudoClassLastChild = "last-child";
private const string pseudoClassEmpty = "empty";
private const string pseudoClassLink = "link";
private const string pseudoClassVisited = "visited";
private const string pseudoClassActive = "active";
private const string pseudoClassHover = "hover";
private const string pseudoClassFocus = "focus";
private const string pseudoClassTarget = "target";
private const string pseudoClassEnabled = "enabled";
private const string pseudoClassDisabled = "disabled";
private const string pseudoClassChecked = "checked";
private const string pseudoClassUnchecked = "unchecked";
private const string pseudoClassIndeterminate = "indeterminate";
private const string pseudoClassDefault = "default";
private const string pseudoClassValid = "valid";
private const string pseudoClassInvalid = "invalid";
private const string pseudoClassRequired = "required";
private const string pseudoClassInRange = "in-range";
private const string pseudoClassOutOfRange = "out-of-range";
private const string pseudoClassOptional = "optional";
private const string pseudoClassReadOnly = "read-only";
private const string pseudoClassReadWrite = "read-write";
private const string pseudoClassFunctionDir = "dir";
private const string pseudoClassFunctionNthChild = "nth-child";
private const string pseudoClassFunctionNthLastChild = "nth-last-child";
private const string pseudoClassFunctionNot = "not";
private const string pseudoClassFunctionLang = "lang";
private const string pseudoClassFunctionContains = "contains";
private const string pseudoElementBefore = "before";
private const string pseudoElementAfter = "after";
private const string pseudoElementSelection = "selection";
private const string pseudoElementFirstLine = "first-line";
private const string pseudoElementFirstLetter = "first-letter";
private static readonly string nthChildOdd = "odd";
private static readonly string nthChildEven = "even";
private static readonly string nthChildN = "n";
private State state;
private ISelector temp;
private ListSelector group;
private ComplexSelector complex;
private bool hasCombinator;
private CssCombinator combinator;
private CssSelectorConstructor nested;
private string attrName;
private string attrValue;
private string attrOp;
public ISelector Result {
get {
if (complex != null) {
complex.ConcludeSelector(temp);
temp = complex;
}
if (group == null || group.Length == 0)
return temp ?? SimpleSelector.All;
if (temp == null && group.Length == 1)
return group[0];
if (temp != null) {
group.Add(temp);
temp = null;
}
return group;
}
}
public CssSelectorConstructor()
{
Reset();
}
public bool Apply(CssToken token)
{
switch (state) {
case State.Data:
return OnData(token);
case State.Class:
return OnClass(token);
case State.Attribute:
return OnAttribute(token);
case State.AttributeOperator:
return OnAttributeOperator(token);
case State.AttributeValue:
return OnAttributeValue(token);
case State.AttributeEnd:
return OnAttributeEnd(token);
case State.PseudoClass:
return OnPseudoClass(token);
case State.PseudoClassFunction:
return OnPseudoClassFunction(token);
case State.PseudoClassFunctionEnd:
return OnPseudoClassFunctionEnd(token);
case State.PseudoElement:
return OnPseudoElement(token);
default:
return false;
}
}
public CssSelectorConstructor Reset()
{
attrName = null;
attrValue = null;
attrOp = string.Empty;
state = State.Data;
combinator = CssCombinator.Descendent;
hasCombinator = false;
temp = null;
group = null;
complex = null;
return this;
}
private bool OnData(CssToken token)
{
switch (token.Type) {
case CssTokenType.SquareBracketOpen:
attrName = null;
attrValue = null;
attrOp = string.Empty;
state = State.Attribute;
return true;
case CssTokenType.Colon:
state = State.PseudoClass;
return true;
case CssTokenType.Hash:
Insert(SimpleSelector.Id(((CssKeywordToken)token).Data));
return true;
case CssTokenType.Ident:
Insert(SimpleSelector.Type(((CssKeywordToken)token).Data));
return true;
case CssTokenType.Whitespace:
Insert(CssCombinator.Descendent);
return true;
case CssTokenType.Delim:
return OnDelim(token);
case CssTokenType.Comma:
InsertOr();
return true;
default:
return false;
}
}
private bool OnAttribute(CssToken token)
{
if (token.Type == CssTokenType.Whitespace)
return true;
state = State.AttributeOperator;
if (token.Type == CssTokenType.Ident)
attrName = ((CssKeywordToken)token).Data;
else {
if (token.Type != 0) {
state = State.Data;
return false;
}
attrName = ((CssStringToken)token).Data;
}
return true;
}
private bool OnAttributeOperator(CssToken token)
{
if (token.Type == CssTokenType.Whitespace)
return true;
state = State.AttributeValue;
if (token.Type == CssTokenType.SquareBracketClose)
return OnAttributeEnd(token);
if (!(token is CssMatchToken) && token.Type != CssTokenType.Delim) {
state = State.AttributeEnd;
return false;
}
attrOp = token.ToValue();
return true;
}
private bool OnAttributeValue(CssToken token)
{
if (token.Type == CssTokenType.Whitespace)
return true;
state = State.AttributeEnd;
if (token.Type == CssTokenType.Ident)
attrValue = ((CssKeywordToken)token).Data;
else if (token.Type == CssTokenType.String) {
attrValue = ((CssStringToken)token).Data;
} else {
if (token.Type != CssTokenType.Number) {
state = State.Data;
return false;
}
attrValue = ((CssNumberToken)token).Data.ToString();
}
return true;
}
private bool OnAttributeEnd(CssToken token)
{
if (token.Type == CssTokenType.Whitespace)
return true;
state = State.Data;
if (token.Type == CssTokenType.SquareBracketClose) {
switch (attrOp) {
case "=":
Insert(SimpleSelector.AttrMatch(attrName, attrValue));
break;
case "~=":
Insert(SimpleSelector.AttrList(attrName, attrValue));
break;
case "|=":
Insert(SimpleSelector.AttrHyphen(attrName, attrValue));
break;
case "^=":
Insert(SimpleSelector.AttrBegins(attrName, attrValue));
break;
case "$=":
Insert(SimpleSelector.AttrEnds(attrName, attrValue));
break;
case "*=":
Insert(SimpleSelector.AttrContains(attrName, attrValue));
break;
case "!=":
Insert(SimpleSelector.AttrNotMatch(attrName, attrValue));
break;
default:
Insert(SimpleSelector.AttrAvailable(attrName));
break;
}
return true;
}
return false;
}
private bool OnPseudoClass(CssToken token)
{
state = State.Data;
if (token.Type == CssTokenType.Colon) {
state = State.PseudoElement;
return true;
}
if (token.Type == CssTokenType.Function) {
attrName = ((CssKeywordToken)token).Data;
attrValue = string.Empty;
state = State.PseudoClassFunction;
if (nested != null)
nested.Reset();
return true;
}
if (token.Type == CssTokenType.Ident) {
ISelector pseudoSelector = GetPseudoSelector(token);
if (pseudoSelector == null)
return false;
Insert(pseudoSelector);
return true;
}
return false;
}
private bool OnPseudoElement(CssToken token)
{
if (token.Type == CssTokenType.Ident) {
string data = ((CssKeywordToken)token).Data;
switch (data) {
case "before":
Insert(SimpleSelector.PseudoElement(MatchBefore, "before"));
return true;
case "after":
Insert(SimpleSelector.PseudoElement(MatchAfter, "after"));
return true;
case "selection":
Insert(SimpleSelector.PseudoElement((IElement el) => true, "selection"));
return true;
case "first-line":
Insert(SimpleSelector.PseudoElement(MatchFirstLine, "first-line"));
return true;
case "first-letter":
Insert(SimpleSelector.PseudoElement(MatchFirstLetter, "first-letter"));
return true;
default:
Insert(SimpleSelector.PseudoElement((IElement el) => false, data));
return false;
}
}
return false;
}
private bool OnClass(CssToken token)
{
state = State.Data;
if (token.Type == CssTokenType.Ident) {
Insert(SimpleSelector.Class(((CssKeywordToken)token).Data));
return true;
}
return false;
}
private bool OnPseudoClassFunction(CssToken token)
{
if (token.Type == CssTokenType.Whitespace)
return true;
switch (attrName) {
case "nth-child":
case "nth-last-child":
switch (token.Type) {
case CssTokenType.Ident:
case CssTokenType.Number:
case CssTokenType.Dimension:
attrValue += token.ToValue();
return true;
case CssTokenType.Delim: {
char data = ((CssDelimToken)token).Data;
if (data == '+' || data == '-') {
attrValue += data;
return true;
}
break;
}
}
break;
case "not":
if (nested == null)
nested = new CssSelectorConstructor();
if (token.Type != CssTokenType.RoundBracketClose || nested.state != 0) {
nested.Apply(token);
return true;
}
break;
case "dir":
if (token.Type == CssTokenType.Ident)
attrValue = ((CssKeywordToken)token).Data;
state = State.PseudoClassFunctionEnd;
return true;
case "lang":
if (token.Type == CssTokenType.Ident)
attrValue = ((CssKeywordToken)token).Data;
state = State.PseudoClassFunctionEnd;
return true;
case "contains":
if (token.Type == CssTokenType.String)
attrValue = ((CssStringToken)token).Data;
else if (token.Type == CssTokenType.Ident) {
attrValue = ((CssKeywordToken)token).Data;
}
state = State.PseudoClassFunctionEnd;
return true;
}
return OnPseudoClassFunctionEnd(token);
}
private bool OnPseudoClassFunctionEnd(CssToken token)
{
state = State.Data;
if (token.Type == CssTokenType.RoundBracketClose) {
switch (attrName) {
case "nth-child": {
ISelector childSelector = GetChildSelector<NthFirstChildSelector>();
if (childSelector == null)
return false;
Insert(childSelector);
return true;
}
case "nth-last-child": {
ISelector childSelector2 = GetChildSelector<NthLastChildSelector>();
if (childSelector2 == null)
return false;
Insert(childSelector2);
return true;
}
case "not": {
ISelector sel = nested.Result;
string pseudoClass4 = "not" + "(" + sel.ToCss() + ")";
Insert(SimpleSelector.PseudoClass((IElement el) => !sel.Match(el), pseudoClass4));
return true;
}
case "dir": {
string pseudoClass2 = "dir" + "(" + attrValue + ")";
Insert(SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IHtmlElement)
return ((IHtmlElement)el).Direction.Equals(attrValue, StringComparison.OrdinalIgnoreCase);
return false;
}, pseudoClass2));
return true;
}
case "lang": {
string pseudoClass3 = "lang" + "(" + attrValue + ")";
Insert(SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IHtmlElement)
return ((IHtmlElement)el).Language.StartsWith(attrValue, StringComparison.OrdinalIgnoreCase);
return false;
}, pseudoClass3));
return true;
}
case "contains": {
string pseudoClass = "contains" + "(" + attrValue + ")";
Insert(SimpleSelector.PseudoClass((IElement el) => el.TextContent.Contains(attrValue), pseudoClass));
return true;
}
default:
return true;
}
}
return false;
}
private void InsertOr()
{
if (temp != null) {
if (group == null)
group = new ListSelector();
if (complex != null) {
complex.ConcludeSelector(temp);
group.Add(complex);
complex = null;
} else
group.Add(temp);
temp = null;
}
}
private void Insert(ISelector selector)
{
if (temp != null) {
if (!hasCombinator) {
CompoundSelector compoundSelector = temp as CompoundSelector;
if (compoundSelector == null) {
compoundSelector = new CompoundSelector();
compoundSelector.Add(temp);
}
compoundSelector.Add(selector);
temp = compoundSelector;
} else {
if (complex == null)
complex = new ComplexSelector();
complex.AppendSelector(temp, combinator);
combinator = CssCombinator.Descendent;
hasCombinator = false;
temp = selector;
}
} else {
combinator = CssCombinator.Descendent;
hasCombinator = false;
temp = selector;
}
}
private void Insert(CssCombinator cssCombinator)
{
hasCombinator = true;
if (cssCombinator != CssCombinator.Descendent)
combinator = cssCombinator;
}
private bool OnDelim(CssToken token)
{
switch (((CssDelimToken)token).Data) {
case ',':
InsertOr();
return true;
case '>':
Insert(CssCombinator.Child);
return true;
case '+':
Insert(CssCombinator.AdjacentSibling);
return true;
case '~':
Insert(CssCombinator.Sibling);
return true;
case '*':
Insert(SimpleSelector.All);
return true;
case '.':
state = State.Class;
return true;
default:
return false;
}
}
private ISelector GetChildSelector<T>() where T : NthChildSelector, ISelector, new
{
new NthFirstChildSelector();
T val = new T();
if (attrValue.Equals(nthChildOdd, StringComparison.OrdinalIgnoreCase)) {
val.step = 2;
val.offset = 1;
} else if (attrValue.Equals(nthChildEven, StringComparison.OrdinalIgnoreCase)) {
val.step = 2;
val.offset = 0;
} else if (!int.TryParse(attrValue, out val.offset)) {
int num = attrValue.IndexOf(nthChildN, StringComparison.OrdinalIgnoreCase);
if (attrValue.Length <= 0 || num == -1)
return null;
string text = attrValue.Substring(0, num).Replace(" ", "");
string text2 = attrValue.Substring(num + 1).Replace(" ", "");
if (text == string.Empty || (text.Length == 1 && text[0] == '+'))
val.step = 1;
else if (text.Length == 1 && text[0] == '-') {
val.step = -1;
} else if (!int.TryParse(text, out val.step)) {
throw new DomException(ErrorCode.Syntax);
}
if (text2 == string.Empty)
val.offset = 0;
else if (!int.TryParse(text2, out val.offset)) {
return null;
}
}
return val;
}
private ISelector GetPseudoSelector(CssToken token)
{
switch (((CssKeywordToken)token).Data) {
case "root":
return SimpleSelector.PseudoClass((IElement el) => el.Owner.DocumentElement == el, "root");
case "first-of-type":
return SimpleSelector.PseudoClass(delegate(IElement el) {
IElement parentElement3 = el.ParentElement;
if (parentElement3 == null)
return true;
for (int j = 0; j < parentElement3.ChildNodes.Length; j++) {
if (parentElement3.ChildNodes[j].NodeName == el.NodeName)
return parentElement3.ChildNodes[j] == el;
}
return false;
}, "first-of-type");
case "last-of-type":
return SimpleSelector.PseudoClass(delegate(IElement el) {
IElement parentElement = el.ParentElement;
if (parentElement == null)
return true;
for (int num = parentElement.ChildNodes.Length - 1; num >= 0; num--) {
if (parentElement.ChildNodes[num].NodeName == el.NodeName)
return parentElement.ChildNodes[num] == el;
}
return false;
}, "last-of-type");
case "only-child":
return SimpleSelector.PseudoClass(delegate(IElement el) {
IElement parentElement2 = el.ParentElement;
if (parentElement2 == null)
return false;
int num2 = 0;
for (int i = 0; i < parentElement2.ChildNodes.Length; i++) {
if (parentElement2.ChildNodes[i] is Element && ++num2 == 2)
return false;
}
return true;
}, "only-child");
case "first-child":
return FirstChildSelector.Instance;
case "last-child":
return LastChildSelector.Instance;
case "empty":
return SimpleSelector.PseudoClass((IElement el) => el.ChildNodes.Length == 0, "empty");
case "link":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLAnchorElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return !((HTMLAnchorElement)el).IsVisited;
return false;
}
if (el is HTMLAreaElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return !((HTMLAreaElement)el).IsVisited;
return false;
}
if (el is HTMLLinkElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return !((HTMLLinkElement)el).IsVisited;
return false;
}
return false;
}, "link");
case "visited":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLAnchorElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLAnchorElement)el).IsVisited;
return false;
}
if (el is HTMLAreaElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLAreaElement)el).IsVisited;
return false;
}
if (el is HTMLLinkElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLLinkElement)el).IsVisited;
return false;
}
return false;
}, "visited");
case "active":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLAnchorElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLAnchorElement)el).IsActive;
return false;
}
if (el is HTMLAreaElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLAreaElement)el).IsActive;
return false;
}
if (el is HTMLLinkElement) {
if (!string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href)))
return ((HTMLLinkElement)el).IsActive;
return false;
}
if (el is HTMLButtonElement) {
if (!((HTMLButtonElement)el).IsDisabled)
return ((HTMLButtonElement)el).IsActive;
return false;
}
if (el is HTMLInputElement) {
HTMLInputElement hTMLInputElement2 = (HTMLInputElement)el;
HTMLInputElement.InputType inputType2 = hTMLInputElement2.Type.ToEnum(HTMLInputElement.InputType.Text);
if (inputType2 == HTMLInputElement.InputType.Submit || inputType2 == HTMLInputElement.InputType.Image || inputType2 == HTMLInputElement.InputType.Reset || inputType2 == HTMLInputElement.InputType.Button)
return hTMLInputElement2.IsActive;
return false;
}
if (el is HTMLMenuItemElement) {
if (string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled)))
return ((HTMLMenuItemElement)el).IsActive;
return false;
}
return false;
}, "active");
case "hover":
return SimpleSelector.PseudoClass((IElement el) => false, "hover");
case "focus":
return SimpleSelector.PseudoClass((IElement el) => false, "focus");
case "target":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el.Owner != null)
return el.Id == el.Owner.Location.Hash;
return false;
}, "target");
case "enabled":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLAnchorElement || el is HTMLAreaElement || el is HTMLLinkElement)
return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Href));
if (el is HTMLButtonElement)
return !((HTMLButtonElement)el).IsDisabled;
if (el is HTMLInputElement)
return !((HTMLInputElement)el).IsDisabled;
if (el is HTMLSelectElement)
return !((HTMLSelectElement)el).IsDisabled;
if (el is HTMLTextAreaElement)
return !((HTMLTextAreaElement)el).IsDisabled;
if (el is HTMLOptionElement)
return !((HTMLOptionElement)el).IsDisabled;
if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement)
return string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled));
return false;
}, "enabled");
case "disabled":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLButtonElement)
return ((HTMLButtonElement)el).IsDisabled;
if (el is HTMLInputElement)
return ((HTMLInputElement)el).IsDisabled;
if (el is HTMLSelectElement)
return ((HTMLSelectElement)el).IsDisabled;
if (el is HTMLTextAreaElement)
return ((HTMLTextAreaElement)el).IsDisabled;
if (el is HTMLOptionElement)
return ((HTMLOptionElement)el).IsDisabled;
if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement)
return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Disabled));
return false;
}, "disabled");
case "default":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLButtonElement) {
HTMLButtonElement hTMLButtonElement = (HTMLButtonElement)el;
IHtmlFormElement form = hTMLButtonElement.Form;
if (form != null)
return true;
} else if (el is HTMLInputElement) {
HTMLInputElement hTMLInputElement3 = (HTMLInputElement)el;
HTMLInputElement.InputType inputType3 = hTMLInputElement3.Type.ToEnum(HTMLInputElement.InputType.Text);
if (inputType3 == HTMLInputElement.InputType.Submit || inputType3 == HTMLInputElement.InputType.Image) {
IHtmlFormElement form2 = hTMLInputElement3.Form;
if (form2 != null)
return true;
}
} else if (el is HTMLOptionElement) {
return !string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Selected));
}
return false;
}, "default");
case "checked":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement) {
HTMLInputElement hTMLInputElement4 = (HTMLInputElement)el;
HTMLInputElement.InputType inputType4 = hTMLInputElement4.Type.ToEnum(HTMLInputElement.InputType.Text);
if (inputType4 == HTMLInputElement.InputType.Checkbox || inputType4 == HTMLInputElement.InputType.Radio)
return hTMLInputElement4.IsChecked;
return false;
}
if (el is HTMLMenuItemElement) {
HTMLMenuItemElement hTMLMenuItemElement2 = (HTMLMenuItemElement)el;
HTMLMenuItemElement.ItemType itemType2 = hTMLMenuItemElement2.Type.ToEnum(HTMLMenuItemElement.ItemType.Command);
if (itemType2 == HTMLMenuItemElement.ItemType.Checkbox || itemType2 == HTMLMenuItemElement.ItemType.Radio)
return hTMLMenuItemElement2.IsChecked;
return false;
}
if (el is HTMLOptionElement)
return ((HTMLOptionElement)el).IsSelected;
return false;
}, "checked");
case "indeterminate":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement) {
HTMLInputElement hTMLInputElement5 = (HTMLInputElement)el;
HTMLInputElement.InputType inputType5 = hTMLInputElement5.Type.ToEnum(HTMLInputElement.InputType.Text);
if (inputType5 == HTMLInputElement.InputType.Checkbox)
return hTMLInputElement5.IsIndeterminate;
return false;
}
if (el is HTMLProgressElement)
return string.IsNullOrEmpty(el.GetAttribute(AttributeNames.Value));
return false;
}, "indeterminate");
case "unchecked":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement) {
HTMLInputElement hTMLInputElement = (HTMLInputElement)el;
HTMLInputElement.InputType inputType = hTMLInputElement.Type.ToEnum(HTMLInputElement.InputType.Text);
if (inputType == HTMLInputElement.InputType.Checkbox || inputType == HTMLInputElement.InputType.Radio)
return !hTMLInputElement.IsChecked;
return false;
}
if (el is HTMLMenuItemElement) {
HTMLMenuItemElement hTMLMenuItemElement = (HTMLMenuItemElement)el;
HTMLMenuItemElement.ItemType itemType = hTMLMenuItemElement.Type.ToEnum(HTMLMenuItemElement.ItemType.Command);
if (itemType == HTMLMenuItemElement.ItemType.Checkbox || itemType == HTMLMenuItemElement.ItemType.Radio)
return !hTMLMenuItemElement.IsChecked;
return false;
}
if (el is HTMLOptionElement)
return !((HTMLOptionElement)el).IsSelected;
return false;
}, "unchecked");
case "valid":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IValidation)
return ((IValidation)el).CheckValidity();
if (el is HTMLFormElement)
return ((HTMLFormElement)el).CheckValidity();
return false;
}, "valid");
case "invalid":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IValidation)
return !((IValidation)el).CheckValidity();
if (el is HTMLFormElement)
return !((HTMLFormElement)el).CheckValidity();
return false;
}, "invalid");
case "required":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement)
return ((HTMLInputElement)el).IsRequired;
if (el is HTMLSelectElement)
return ((HTMLSelectElement)el).IsRequired;
if (el is HTMLTextAreaElement)
return ((HTMLTextAreaElement)el).IsRequired;
return false;
}, "required");
case "read-only":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement)
return !((HTMLInputElement)el).IsMutable;
if (el is HTMLTextAreaElement)
return !((HTMLTextAreaElement)el).IsMutable;
if (el is IHtmlElement)
return !((IHtmlElement)el).IsContentEditable;
return true;
}, "read-only");
case "read-write":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement)
return ((HTMLInputElement)el).IsMutable;
if (el is HTMLTextAreaElement)
return ((HTMLTextAreaElement)el).IsMutable;
if (el is IHtmlElement)
return ((IHtmlElement)el).IsContentEditable;
return false;
}, "read-write");
case "in-range":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IValidation) {
IValidityState validity = ((IValidation)el).Validity;
if (!validity.IsRangeOverflow)
return !validity.IsRangeUnderflow;
return false;
}
return false;
}, "in-range");
case "out-of-range":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is IValidation) {
IValidityState validity2 = ((IValidation)el).Validity;
if (!validity2.IsRangeOverflow)
return validity2.IsRangeUnderflow;
return true;
}
return false;
}, "out-of-range");
case "optional":
return SimpleSelector.PseudoClass(delegate(IElement el) {
if (el is HTMLInputElement)
return !((HTMLInputElement)el).IsRequired;
if (el is HTMLSelectElement)
return !((HTMLSelectElement)el).IsRequired;
if (el is HTMLTextAreaElement)
return !((HTMLTextAreaElement)el).IsRequired;
return false;
}, "optional");
case "before":
return SimpleSelector.PseudoClass(MatchBefore, "before");
case "after":
return SimpleSelector.PseudoClass(MatchAfter, "after");
case "first-line":
return SimpleSelector.PseudoClass(MatchFirstLine, "first-line");
case "first-letter":
return SimpleSelector.PseudoClass(MatchFirstLetter, "first-letter");
default:
return null;
}
}
private static bool MatchBefore(IElement element)
{
return true;
}
private static bool MatchAfter(IElement element)
{
return true;
}
private static bool MatchFirstLine(IElement element)
{
return true;
}
private static bool MatchFirstLetter(IElement element)
{
return true;
}
}
}