public override ISelector Produce()
            {
                var valid = _nested.IsValid;
                var sel   = _nested.ToPool();

                if (!valid)
                {
                    return(null);
                }

                return(SimpleSelector.PseudoClass(el =>
                {
                    var host = default(IElement);
                    var shadowRoot = el.Parent as IShadowRoot;

                    if (shadowRoot != null)
                    {
                        host = shadowRoot.Host;
                    }

                    while (host != null)
                    {
                        if (sel.Match(host))
                        {
                            return true;
                        }

                        host = host.ParentElement;
                    }

                    return false;
                }, String.Concat(PseudoClassNames.HostContext, "(", sel.Text, ")")));
            }
Example #2
0
            public override ISelector Produce()
            {
                var valid = _selector.IsValid;
                var sel   = _selector.GetResult();

                if (valid)
                {
                    var code = PseudoClassNames.HostContext.CssFunction(sel.Text);
                    return(SimpleSelector.PseudoClass(el =>
                    {
                        var host = default(IElement);
                        var shadowRoot = el.Parent as IShadowRoot;

                        if (shadowRoot != null)
                        {
                            host = shadowRoot.Host;
                        }

                        while (host != null)
                        {
                            if (sel.Match(host))
                            {
                                return true;
                            }

                            host = host.ParentElement;
                        }

                        return false;
                    }, code));
                }

                return(null);
            }
Example #3
0
        static CssSelectorConstructor()
        {
            pseudoClassSelectors.Add(PseudoClassNames.Root, SimpleSelector.PseudoClass(el => el.Owner.DocumentElement == el, PseudoClassNames.Root));
            pseudoClassSelectors.Add(PseudoClassNames.OnlyType, SimpleSelector.PseudoClass(el => el.IsOnlyOfType(), PseudoClassNames.OnlyType));
            pseudoClassSelectors.Add(PseudoClassNames.FirstOfType, SimpleSelector.PseudoClass(el => el.IsFirstOfType(), PseudoClassNames.FirstOfType));
            pseudoClassSelectors.Add(PseudoClassNames.LastOfType, SimpleSelector.PseudoClass(el => el.IsLastOfType(), PseudoClassNames.LastOfType));
            pseudoClassSelectors.Add(PseudoClassNames.OnlyChild, SimpleSelector.PseudoClass(el => el.IsOnlyChild(), PseudoClassNames.OnlyChild));
            pseudoClassSelectors.Add(PseudoClassNames.FirstChild, SimpleSelector.PseudoClass(el => el.IsFirstChild(), PseudoClassNames.FirstChild));
            pseudoClassSelectors.Add(PseudoClassNames.LastChild, SimpleSelector.PseudoClass(el => el.IsLastChild(), PseudoClassNames.LastChild));
            pseudoClassSelectors.Add(PseudoClassNames.Empty, SimpleSelector.PseudoClass(el => el.ChildElementCount == 0 && el.TextContent.Equals(String.Empty), PseudoClassNames.Empty));
            pseudoClassSelectors.Add(PseudoClassNames.AnyLink, SimpleSelector.PseudoClass(el => el.IsLink() || el.IsVisited(), PseudoClassNames.AnyLink));
            pseudoClassSelectors.Add(PseudoClassNames.Link, SimpleSelector.PseudoClass(el => el.IsLink(), PseudoClassNames.Link));
            pseudoClassSelectors.Add(PseudoClassNames.Visited, SimpleSelector.PseudoClass(el => el.IsVisited(), PseudoClassNames.Visited));
            pseudoClassSelectors.Add(PseudoClassNames.Active, SimpleSelector.PseudoClass(el => el.IsActive(), PseudoClassNames.Active));
            pseudoClassSelectors.Add(PseudoClassNames.Hover, SimpleSelector.PseudoClass(el => el.IsHovered(), PseudoClassNames.Hover));
            pseudoClassSelectors.Add(PseudoClassNames.Focus, SimpleSelector.PseudoClass(el => el.IsFocused, PseudoClassNames.Focus));
            pseudoClassSelectors.Add(PseudoClassNames.Target, SimpleSelector.PseudoClass(el => el.IsTarget(), PseudoClassNames.Target));
            pseudoClassSelectors.Add(PseudoClassNames.Enabled, SimpleSelector.PseudoClass(el => el.IsEnabled(), PseudoClassNames.Enabled));
            pseudoClassSelectors.Add(PseudoClassNames.Disabled, SimpleSelector.PseudoClass(el => el.IsDisabled(), PseudoClassNames.Disabled));
            pseudoClassSelectors.Add(PseudoClassNames.Default, SimpleSelector.PseudoClass(el => el.IsDefault(), PseudoClassNames.Default));
            pseudoClassSelectors.Add(PseudoClassNames.Checked, SimpleSelector.PseudoClass(el => el.IsChecked(), PseudoClassNames.Checked));
            pseudoClassSelectors.Add(PseudoClassNames.Indeterminate, SimpleSelector.PseudoClass(el => el.IsIndeterminate(), PseudoClassNames.Indeterminate));
            pseudoClassSelectors.Add(PseudoClassNames.PlaceholderShown, SimpleSelector.PseudoClass(el => el.IsPlaceholderShown(), PseudoClassNames.PlaceholderShown));
            pseudoClassSelectors.Add(PseudoClassNames.Unchecked, SimpleSelector.PseudoClass(el => el.IsUnchecked(), PseudoClassNames.Unchecked));
            pseudoClassSelectors.Add(PseudoClassNames.Valid, SimpleSelector.PseudoClass(el => el.IsValid(), PseudoClassNames.Valid));
            pseudoClassSelectors.Add(PseudoClassNames.Invalid, SimpleSelector.PseudoClass(el => el.IsInvalid(), PseudoClassNames.Invalid));
            pseudoClassSelectors.Add(PseudoClassNames.Required, SimpleSelector.PseudoClass(el => el.IsRequired(), PseudoClassNames.Required));
            pseudoClassSelectors.Add(PseudoClassNames.ReadOnly, SimpleSelector.PseudoClass(el => el.IsReadOnly(), PseudoClassNames.ReadOnly));
            pseudoClassSelectors.Add(PseudoClassNames.ReadWrite, SimpleSelector.PseudoClass(el => el.IsEditable(), PseudoClassNames.ReadWrite));
            pseudoClassSelectors.Add(PseudoClassNames.InRange, SimpleSelector.PseudoClass(el => el.IsInRange(), PseudoClassNames.InRange));
            pseudoClassSelectors.Add(PseudoClassNames.OutOfRange, SimpleSelector.PseudoClass(el => el.IsOutOfRange(), PseudoClassNames.OutOfRange));
            pseudoClassSelectors.Add(PseudoClassNames.Optional, SimpleSelector.PseudoClass(el => el.IsOptional(), PseudoClassNames.Optional));

            pseudoElementSelectors.Add(PseudoElementNames.Before, SimpleSelector.PseudoElement(el => el.IsPseudo("::" + PseudoElementNames.Before), PseudoElementNames.Before));
            pseudoElementSelectors.Add(PseudoElementNames.After, SimpleSelector.PseudoElement(el => el.IsPseudo("::" + PseudoElementNames.After), PseudoElementNames.After));
            pseudoElementSelectors.Add(PseudoElementNames.Selection, SimpleSelector.PseudoElement(el => false, PseudoElementNames.Selection));
            pseudoElementSelectors.Add(PseudoElementNames.FirstLine, SimpleSelector.PseudoElement(el => el.HasChildNodes && el.ChildNodes[0].NodeType == NodeType.Text, PseudoElementNames.FirstLine));
            pseudoElementSelectors.Add(PseudoElementNames.FirstLetter, SimpleSelector.PseudoElement(el => el.HasChildNodes && el.ChildNodes[0].NodeType == NodeType.Text && el.ChildNodes[0].TextContent.Length > 0, PseudoElementNames.FirstLetter));

            // LEGACY STYLE OF DEFINING PSEUDO ELEMENTS - AS PSEUDO CLASS!
            pseudoClassSelectors.Add(PseudoElementNames.Before, pseudoElementSelectors[PseudoElementNames.Before]);
            pseudoClassSelectors.Add(PseudoElementNames.After, pseudoElementSelectors[PseudoElementNames.After]);
            pseudoClassSelectors.Add(PseudoElementNames.FirstLine, pseudoElementSelectors[PseudoElementNames.FirstLine]);
            pseudoClassSelectors.Add(PseudoElementNames.FirstLetter, pseudoElementSelectors[PseudoElementNames.FirstLetter]);

            pseudoClassFunctions.Add(PseudoClassNames.NthChild, () => new ChildFunctionState <NthFirstChildSelector>(withOptionalSelector: true));
            pseudoClassFunctions.Add(PseudoClassNames.NthLastChild, () => new ChildFunctionState <NthLastChildSelector>(withOptionalSelector: true));
            pseudoClassFunctions.Add(PseudoClassNames.NthOfType, () => new ChildFunctionState <NthFirstTypeSelector>(withOptionalSelector: false));
            pseudoClassFunctions.Add(PseudoClassNames.NthLastOfType, () => new ChildFunctionState <NthLastTypeSelector>(withOptionalSelector: false));
            pseudoClassFunctions.Add(PseudoClassNames.NthColumn, () => new ChildFunctionState <NthFirstColumnSelector>(withOptionalSelector: false));
            pseudoClassFunctions.Add(PseudoClassNames.NthLastColumn, () => new ChildFunctionState <NthLastColumnSelector>(withOptionalSelector: false));
            pseudoClassFunctions.Add(PseudoClassNames.Not, () => new NotFunctionState());
            pseudoClassFunctions.Add(PseudoClassNames.Dir, () => new DirFunctionState());
            pseudoClassFunctions.Add(PseudoClassNames.Lang, () => new LangFunctionState());
            pseudoClassFunctions.Add(PseudoClassNames.Contains, () => new ContainsFunctionState());
            pseudoClassFunctions.Add(PseudoClassNames.Has, () => new HasFunctionState());
            pseudoClassFunctions.Add(PseudoClassNames.Matches, () => new MatchesFunctionState());
        }
Example #4
0
            public override ISelector Produce()
            {
                if (_valid && _value != null)
                {
                    var code = PseudoClassNames.Contains.CssFunction(_value);
                    return(SimpleSelector.PseudoClass(el => el.TextContent.Contains(_value), code));
                }

                return(null);
            }
Example #5
0
            public override ISelector Produce()
            {
                if (_valid && _value != null)
                {
                    var code = PseudoClassNames.Dir.CssFunction(_value);
                    return(SimpleSelector.PseudoClass(el => el is IHtmlElement && _value.Isi(((IHtmlElement)el).Direction), code));
                }

                return(null);
            }
Example #6
0
            public override ISelector Produce()
            {
                if (valid && value != null)
                {
                    var code = PseudoClassNames.Lang.CssFunction(value);
                    return(SimpleSelector.PseudoClass(el => el is IHtmlElement && ((IHtmlElement)el).Language.StartsWith(value, StringComparison.OrdinalIgnoreCase), code));
                }

                return(null);
            }
Example #7
0
            public override ISelector Produce()
            {
                if (!valid || value == null)
                {
                    return(null);
                }

                var code = String.Concat(PseudoClassNames.Contains, "(", value, ")");

                return(SimpleSelector.PseudoClass(el => el.TextContent.Contains(value), code));
            }
Example #8
0
            public override ISelector Produce()
            {
                var sel = _nested.ToPool();

                if (sel == null)
                {
                    return(null);
                }

                return(SimpleSelector.PseudoClass(el => sel.Match(el), String.Concat(PseudoClassNames.Matches, "(", sel.Text, ")")));
            }
Example #9
0
            public override ISelector Produce()
            {
                if (!valid || value == null)
                {
                    return(null);
                }

                var code = String.Concat(PseudoClassNames.Lang, "(", value, ")");

                return(SimpleSelector.PseudoClass(el => el is IHtmlElement && ((IHtmlElement)el).Language.StartsWith(value, StringComparison.OrdinalIgnoreCase), code));
            }
        /// <summary>
        /// Creates or gets the associated CSS pseudo class selector.
        /// </summary>
        /// <param name="name">The name of the CSS pseudo class.</param>
        /// <returns>The associated selector.</returns>
        public ISelector Create(String name)
        {
            var selector = default(ISelector);

            if (selectors.TryGetValue(name, out selector))
            {
                return(selector);
            }

            return(SimpleSelector.PseudoClass(el => false, name));
        }
            public override ISelector Produce()
            {
                if (!valid || value == null)
                {
                    return(null);
                }

                var code = String.Concat(PseudoClassNames.Dir, "(", value, ")");

                return(SimpleSelector.PseudoClass(el => el is IHtmlElement && value.Isi(((IHtmlElement)el).Direction), code));
            }
Example #12
0
            public override ISelector Produce()
            {
                var sel = _nested.ToPool();

                if (sel == null)
                {
                    return(null);
                }

                return(SimpleSelector.PseudoClass(el => el.ChildNodes.QuerySelector(sel) != null, String.Concat(PseudoClassNames.Has, "(", sel.Text, ")")));
            }
            public override ISelector Produce()
            {
                var valid = _nested.IsValid;
                var sel   = _nested.ToPool();

                if (!valid)
                {
                    return(null);
                }

                return(SimpleSelector.PseudoClass(el => !sel.Match(el), String.Concat(PseudoClassNames.Not, "(", sel.Text, ")")));
            }
Example #14
0
            public override ISelector Produce()
            {
                var valid = _selector.IsValid;
                var sel   = _selector.GetResult();

                if (valid)
                {
                    var code = PseudoClassNames.Matches.CssFunction(sel.Text);
                    return(SimpleSelector.PseudoClass(el => sel.Match(el), code));
                }

                return(null);
            }
Example #15
0
            public override ISelector Produce()
            {
                var valid = _nested.IsValid;
                var sel   = _nested.GetResult();

                if (valid)
                {
                    var code = PseudoClassNames.Has.CssFunction(sel.Text);
                    return(SimpleSelector.PseudoClass(el => el.ChildNodes.QuerySelector(sel) != null, code));
                }

                return(null);
            }
            public override ISelector Produce()
            {
                var valid = _nested.IsValid;
                var sel   = _nested.ToPool();

                if (!valid)
                {
                    return(null);
                }

                var code = PseudoClassNames.Matches.CssFunction(sel.Text);

                return(SimpleSelector.PseudoClass(el => sel.Match(el), code));
            }
        /// <summary>
        /// Invoked once a colon with an identifier has been found in the token enumerator.
        /// </summary>
        /// <returns>The created selector.</returns>
        ISelector GetPseudoSelector(CssToken token)
        {
            switch (token.Data)
            {
            case pseudoClassRoot:
                return(SimpleSelector.PseudoClass(el => el.Owner.DocumentElement == el, pseudoClassRoot));

            case pseudoClassFirstOfType:
                return(SimpleSelector.PseudoClass(el =>
                {
                    var parent = el.ParentElement;

                    if (parent == null)
                    {
                        return true;
                    }

                    for (int i = 0; i < parent.ChildNodes.Length; i++)
                    {
                        if (parent.ChildNodes[i].NodeName == el.NodeName)
                        {
                            return parent.ChildNodes[i] == el;
                        }
                    }

                    return false;
                }, pseudoClassFirstOfType));

            case pseudoClassLastOfType:
                return(SimpleSelector.PseudoClass(el =>
                {
                    var parent = el.ParentElement;

                    if (parent == null)
                    {
                        return true;
                    }

                    for (int i = parent.ChildNodes.Length - 1; i >= 0; i--)
                    {
                        if (parent.ChildNodes[i].NodeName == el.NodeName)
                        {
                            return parent.ChildNodes[i] == el;
                        }
                    }

                    return false;
                }, pseudoClassLastOfType));

            case pseudoClassOnlyChild:
                return(SimpleSelector.PseudoClass(el => el.IsOnlyChild(), pseudoClassOnlyChild));

            case pseudoClassFirstChild:
                return(FirstChildSelector.Instance);

            case pseudoClassLastChild:
                return(LastChildSelector.Instance);

            case pseudoClassEmpty:
                return(SimpleSelector.PseudoClass(el => el.ChildNodes.Length == 0, pseudoClassEmpty));

            case pseudoClassLink:
                return(SimpleSelector.PseudoClass(el => el.IsLink(), pseudoClassLink));

            case pseudoClassVisited:
                return(SimpleSelector.PseudoClass(el => el.IsVisited(), pseudoClassVisited));

            case pseudoClassActive:
                return(SimpleSelector.PseudoClass(el => el.IsActive(), pseudoClassActive));

            case pseudoClassHover:
                return(SimpleSelector.PseudoClass(el => el.IsHovered(), pseudoClassHover));

            case pseudoClassFocus:
                return(SimpleSelector.PseudoClass(el => el.IsFocused(), pseudoClassFocus));

            case pseudoClassTarget:
                return(SimpleSelector.PseudoClass(el => el.Owner != null && el.Id == el.Owner.Location.Hash, pseudoClassTarget));

            case pseudoClassEnabled:
                return(SimpleSelector.PseudoClass(el => el.IsEnabled(), pseudoClassEnabled));

            case pseudoClassDisabled:
                return(SimpleSelector.PseudoClass(el => el.IsDisabled(), pseudoClassDisabled));

            case pseudoClassDefault:
                return(SimpleSelector.PseudoClass(el => el.IsDefault(), pseudoClassDefault));

            case pseudoClassChecked:
                return(SimpleSelector.PseudoClass(el => el.IsChecked(), pseudoClassChecked));

            case pseudoClassIndeterminate:
                return(SimpleSelector.PseudoClass(el => el.IsIndeterminate(), pseudoClassIndeterminate));

            case pseudoClassUnchecked:
                return(SimpleSelector.PseudoClass(el => el.IsUnchecked(), pseudoClassUnchecked));

            case pseudoClassValid:
                return(SimpleSelector.PseudoClass(el => el.IsValid(), pseudoClassValid));

            case pseudoClassInvalid:
                return(SimpleSelector.PseudoClass(el => el.IsInvalid(), pseudoClassInvalid));

            case pseudoClassRequired:
                return(SimpleSelector.PseudoClass(el => el.IsRequired(), pseudoClassRequired));

            case pseudoClassReadOnly:
                return(SimpleSelector.PseudoClass(el => el.IsReadOnly(), pseudoClassReadOnly));

            case pseudoClassReadWrite:
                return(SimpleSelector.PseudoClass(el => el.IsEditable(), pseudoClassReadWrite));

            case pseudoClassInRange:
                return(SimpleSelector.PseudoClass(el => el.IsInRange(), pseudoClassInRange));

            case pseudoClassOutOfRange:
                return(SimpleSelector.PseudoClass(el => el.IsOutOfRange(), pseudoClassOutOfRange));

            case pseudoClassOptional:
                return(SimpleSelector.PseudoClass(el => el.IsOptional(), pseudoClassOptional));

            // LEGACY STYLE OF DEFINING PSEUDO ELEMENTS - AS PSEUDO CLASS!
            case pseudoElementBefore:
                return(SimpleSelector.PseudoClass(MatchBefore, pseudoElementBefore));

            case pseudoElementAfter:
                return(SimpleSelector.PseudoClass(MatchAfter, pseudoElementAfter));

            case pseudoElementFirstLine:
                return(SimpleSelector.PseudoClass(MatchFirstLine, pseudoElementFirstLine));

            case pseudoElementFirstLetter:
                return(SimpleSelector.PseudoClass(MatchFirstLetter, pseudoElementFirstLetter));
            }

            return(null);
        }
Example #18
0
        /// <summary>
        /// Invoked once a colon with an identifier has been found in the token enumerator.
        /// </summary>
        /// <param name="tokens">The token source.</param>
        /// <returns>The created selector.</returns>
        public SimpleSelector GetPseudoClassIdentifier(IEnumerator <CssToken> tokens)
        {
            switch (((CssKeywordToken)tokens.Current).Data)
            {
            case PSEUDOCLASS_ROOT:
                return(SimpleSelector.PseudoClass(el => el.OwnerDocument.DocumentElement == el, PSEUDOCLASS_ROOT));

            case PSEUDOCLASS_FIRSTOFTYPE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    var parent = el.ParentElement;

                    if (parent == null)
                    {
                        return true;
                    }

                    for (int i = 0; i < parent.ChildNodes.Length; i++)
                    {
                        if (parent.ChildNodes[i].NodeName == el.NodeName)
                        {
                            return parent.ChildNodes[i] == el;
                        }
                    }

                    return false;
                }, PSEUDOCLASS_FIRSTOFTYPE));

            case PSEUDOCLASS_LASTOFTYPE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    var parent = el.ParentElement;

                    if (parent == null)
                    {
                        return true;
                    }

                    for (int i = parent.ChildNodes.Length - 1; i >= 0; i--)
                    {
                        if (parent.ChildNodes[i].NodeName == el.NodeName)
                        {
                            return parent.ChildNodes[i] == el;
                        }
                    }

                    return false;
                }, PSEUDOCLASS_LASTOFTYPE));

            case PSEUDOCLASS_ONLYCHILD:
                return(SimpleSelector.PseudoClass(el =>
                {
                    var parent = el.ParentElement;

                    if (parent == null)
                    {
                        return false;
                    }

                    var elements = 0;

                    for (int i = 0; i < parent.ChildNodes.Length; i++)
                    {
                        if (parent.ChildNodes[i] is Element && ++elements == 2)
                        {
                            return false;
                        }
                    }

                    return true;
                }, PSEUDOCLASS_ONLYCHILD));

            case PSEUDOCLASS_FIRSTCHILD:
                return(FirstChildSelector.Instance);

            case PSEUDOCLASS_LASTCHILD:
                return(LastChildSelector.Instance);

            case PSEUDOCLASS_EMPTY:
                return(SimpleSelector.PseudoClass(el => el.ChildNodes.Length == 0, PSEUDOCLASS_EMPTY));

            case PSEUDOCLASS_LINK:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLAnchorElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && !((HTMLAnchorElement)el).IsVisited;
                    }
                    else if (el is HTMLAreaElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && !((HTMLAreaElement)el).IsVisited;
                    }
                    else if (el is HTMLLinkElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && !((HTMLLinkElement)el).IsVisited;
                    }

                    return false;
                }, PSEUDOCLASS_LINK));

            case PSEUDOCLASS_VISITED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLAnchorElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLAnchorElement)el).IsVisited;
                    }
                    else if (el is HTMLAreaElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLAreaElement)el).IsVisited;
                    }
                    else if (el is HTMLLinkElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLLinkElement)el).IsVisited;
                    }

                    return false;
                }, PSEUDOCLASS_VISITED));

            case PSEUDOCLASS_ACTIVE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLAnchorElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLAnchorElement)el).IsActive;
                    }
                    else if (el is HTMLAreaElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLAreaElement)el).IsActive;
                    }
                    else if (el is HTMLLinkElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href")) && ((HTMLLinkElement)el).IsActive;
                    }
                    else if (el is HTMLButtonElement)
                    {
                        return !((HTMLButtonElement)el).Disabled && ((HTMLButtonElement)el).IsActive;
                    }
                    else if (el is HTMLInputElement)
                    {
                        var inp = (HTMLInputElement)el;
                        return (inp.Type == HTMLInputElement.InputType.Submit || inp.Type == HTMLInputElement.InputType.Image ||
                                inp.Type == HTMLInputElement.InputType.Reset || inp.Type == HTMLInputElement.InputType.Button) &&
                        inp.IsActive;
                    }
                    else if (el is HTMLMenuItemElement)
                    {
                        return string.IsNullOrEmpty(el.GetAttribute("disabled")) && ((HTMLMenuItemElement)el).IsActive;
                    }

                    return false;
                }, PSEUDOCLASS_ACTIVE));

            case PSEUDOCLASS_HOVER:
                return(SimpleSelector.PseudoClass(el => el.IsHovered, PSEUDOCLASS_HOVER));

            case PSEUDOCLASS_FOCUS:
                return(SimpleSelector.PseudoClass(el => el.IsFocused, PSEUDOCLASS_FOCUS));

            case PSEUDOCLASS_TARGET:
                return(SimpleSelector.PseudoClass(el => el.OwnerDocument != null && el.Id == el.OwnerDocument.Location.Hash, PSEUDOCLASS_TARGET));

            case PSEUDOCLASS_ENABLED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLAnchorElement || el is HTMLAreaElement || el is HTMLLinkElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("href"));
                    }
                    else if (el is HTMLButtonElement)
                    {
                        return !((HTMLButtonElement)el).Disabled;
                    }
                    else if (el is HTMLInputElement)
                    {
                        return !((HTMLInputElement)el).Disabled;
                    }
                    else if (el is HTMLSelectElement)
                    {
                        return !((HTMLSelectElement)el).Disabled;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return !((HTMLTextAreaElement)el).Disabled;
                    }
                    else if (el is HTMLOptionElement)
                    {
                        return !((HTMLOptionElement)el).Disabled;
                    }
                    else if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement)
                    {
                        return string.IsNullOrEmpty(el.GetAttribute("disabled"));
                    }

                    return false;
                }, PSEUDOCLASS_ENABLED));

            case PSEUDOCLASS_DISABLED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLButtonElement)
                    {
                        return ((HTMLButtonElement)el).Disabled;
                    }
                    else if (el is HTMLInputElement)
                    {
                        return ((HTMLInputElement)el).Disabled;
                    }
                    else if (el is HTMLSelectElement)
                    {
                        return ((HTMLSelectElement)el).Disabled;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return ((HTMLTextAreaElement)el).Disabled;
                    }
                    else if (el is HTMLOptionElement)
                    {
                        return ((HTMLOptionElement)el).Disabled;
                    }
                    else if (el is HTMLOptGroupElement || el is HTMLMenuItemElement || el is HTMLFieldSetElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("disabled"));
                    }

                    return false;
                }, PSEUDOCLASS_DISABLED));

            case PSEUDOCLASS_DEFAULT:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLButtonElement)
                    {
                        var bt = (HTMLButtonElement)el;
                        var form = bt.Form;

                        if (form != null)    //TODO Check if button is form def. button
                        {
                            return true;
                        }
                    }
                    else if (el is HTMLInputElement)
                    {
                        var input = (HTMLInputElement)el;

                        if (input.Type == HTMLInputElement.InputType.Submit || input.Type == HTMLInputElement.InputType.Image)
                        {
                            var form = input.Form;

                            if (form != null)    //TODO Check if input is form def. button
                            {
                                return true;
                            }
                        }
                        else
                        {
                            //TODO input that are checked and can be checked ...
                        }
                    }
                    else if (el is HTMLOptionElement)
                    {
                        return !string.IsNullOrEmpty(el.GetAttribute("selected"));
                    }

                    return false;
                }, PSEUDOCLASS_DEFAULT));

            case PSEUDOCLASS_CHECKED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        var inp = (HTMLInputElement)el;
                        return (inp.Type == HTMLInputElement.InputType.Checkbox || inp.Type == HTMLInputElement.InputType.Radio) &&
                        inp.Checked;
                    }
                    else if (el is HTMLMenuItemElement)
                    {
                        var mi = (HTMLMenuItemElement)el;
                        return (mi.Type == HTMLMenuItemElement.ItemType.Checkbox || mi.Type == HTMLMenuItemElement.ItemType.Radio) &&
                        mi.Checked;
                    }
                    else if (el is HTMLOptionElement)
                    {
                        return ((HTMLOptionElement)el).Selected;
                    }

                    return false;
                }, PSEUDOCLASS_CHECKED));

            case PSEUDOCLASS_INDETERMINATE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        var inp = (HTMLInputElement)el;
                        return inp.Type == HTMLInputElement.InputType.Checkbox && inp.Indeterminate;
                    }
                    else if (el is HTMLProgressElement)
                    {
                        return string.IsNullOrEmpty(el.GetAttribute("value"));
                    }

                    return false;
                }, PSEUDOCLASS_INDETERMINATE));

            case PSEUDOCLASS_UNCHECKED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        var inp = (HTMLInputElement)el;
                        return (inp.Type == HTMLInputElement.InputType.Checkbox || inp.Type == HTMLInputElement.InputType.Radio) &&
                        !inp.Checked;
                    }
                    else if (el is HTMLMenuItemElement)
                    {
                        var mi = (HTMLMenuItemElement)el;
                        return (mi.Type == HTMLMenuItemElement.ItemType.Checkbox || mi.Type == HTMLMenuItemElement.ItemType.Radio) &&
                        !mi.Checked;
                    }
                    else if (el is HTMLOptionElement)
                    {
                        return !((HTMLOptionElement)el).Selected;
                    }

                    return false;
                }, PSEUDOCLASS_UNCHECKED));

            case PSEUDOCLASS_VALID:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is IValidation)
                    {
                        return ((IValidation)el).CheckValidity();
                    }
                    else if (el is HTMLFormElement)
                    {
                        return ((HTMLFormElement)el).IsValid;
                    }

                    return false;
                }, PSEUDOCLASS_VALID));

            case PSEUDOCLASS_INVALID:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is IValidation)
                    {
                        return !((IValidation)el).CheckValidity();
                    }
                    else if (el is HTMLFormElement)
                    {
                        return !((HTMLFormElement)el).IsValid;
                    }
                    else if (el is HTMLFieldSetElement)
                    {
                        return ((HTMLFieldSetElement)el).IsInvalid;
                    }

                    return false;
                }, PSEUDOCLASS_INVALID));

            case PSEUDOCLASS_REQUIRED:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        return ((HTMLInputElement)el).Required;
                    }
                    else if (el is HTMLSelectElement)
                    {
                        return ((HTMLSelectElement)el).Required;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return ((HTMLTextAreaElement)el).Required;
                    }

                    return false;
                }, PSEUDOCLASS_REQUIRED));

            case PSEUDOCLASS_READONLY:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        return !((HTMLInputElement)el).IsMutable;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return !((HTMLTextAreaElement)el).IsMutable;
                    }

                    return !el.IsContentEditable;
                }, PSEUDOCLASS_READONLY));

            case PSEUDOCLASS_READWRITE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        return ((HTMLInputElement)el).IsMutable;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return ((HTMLTextAreaElement)el).IsMutable;
                    }

                    return el.IsContentEditable;
                }, PSEUDOCLASS_READWRITE));

            case PSEUDOCLASS_INRANGE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is IValidation)
                    {
                        var state = ((IValidation)el).Validity;
                        return !state.RangeOverflow && !state.RangeUnderflow;
                    }

                    return false;
                }, PSEUDOCLASS_INRANGE));

            case PSEUDOCLASS_OUTOFRANGE:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is IValidation)
                    {
                        var state = ((IValidation)el).Validity;
                        return state.RangeOverflow || state.RangeUnderflow;
                    }

                    return false;
                }, PSEUDOCLASS_OUTOFRANGE));

            case PSEUDOCLASS_OPTIONAL:
                return(SimpleSelector.PseudoClass(el =>
                {
                    if (el is HTMLInputElement)
                    {
                        return !((HTMLInputElement)el).Required;
                    }
                    else if (el is HTMLSelectElement)
                    {
                        return !((HTMLSelectElement)el).Required;
                    }
                    else if (el is HTMLTextAreaElement)
                    {
                        return !((HTMLTextAreaElement)el).Required;
                    }

                    return false;
                }, PSEUDOCLASS_OPTIONAL));

            // LEGACY STYLE OF DEFINING PSEUDO ELEMENTS - AS PSEUDO CLASS!
            case PSEUDOELEMENT_BEFORE:
                return(SimpleSelector.PseudoClass(MatchBefore, PSEUDOELEMENT_BEFORE));

            case PSEUDOELEMENT_AFTER:
                return(SimpleSelector.PseudoClass(MatchAfter, PSEUDOELEMENT_AFTER));

            case PSEUDOELEMENT_FIRSTLINE:
                return(SimpleSelector.PseudoClass(MatchFirstLine, PSEUDOELEMENT_FIRSTLINE));

            case PSEUDOELEMENT_FIRSTLETTER:
                return(SimpleSelector.PseudoClass(MatchFirstLetter, PSEUDOELEMENT_FIRSTLETTER));
            }

            return(null);
        }
        /// <summary>
        /// Invoked once a pseudo class has been found in the token enumerator.
        /// </summary>
        /// <param name="token">The token.</param>
        /// <returns>True if no error occurred, otherwise false.</returns>
        Boolean OnPseudoClassFunctionEnd(CssToken token)
        {
            state = State.Data;

            if (token.Type == CssTokenType.RoundBracketClose)
            {
                switch (attrName)
                {
                case pseudoClassFunctionNthChild:
                {
                    var sel = GetChildSelector <NthFirstChildSelector>();

                    if (sel == null)
                    {
                        return(false);
                    }

                    Insert(sel);
                    return(true);
                }

                case pseudoClassFunctionNthLastChild:
                {
                    var sel = GetChildSelector <NthLastChildSelector>();

                    if (sel == null)
                    {
                        return(false);
                    }

                    Insert(sel);
                    return(true);
                }

                case pseudoClassFunctionNot:
                {
                    var sel  = nested.Result;
                    var code = String.Concat(pseudoClassFunctionNot, "(", sel.ToCss(), ")");
                    Insert(SimpleSelector.PseudoClass(el => !sel.Match(el), code));
                    return(true);
                }

                case pseudoClassFunctionDir:
                {
                    var code = String.Concat(pseudoClassFunctionDir, "(", attrValue, ")");
                    Insert(SimpleSelector.PseudoClass(el => el is IHtmlElement && ((IHtmlElement)el).Direction.Equals(attrValue, StringComparison.OrdinalIgnoreCase), code));
                    return(true);
                }

                case pseudoClassFunctionLang:
                {
                    var code = String.Concat(pseudoClassFunctionLang, "(", attrValue, ")");
                    Insert(SimpleSelector.PseudoClass(el => el is IHtmlElement && ((IHtmlElement)el).Language.StartsWith(attrValue, StringComparison.OrdinalIgnoreCase), code));
                    return(true);
                }

                case pseudoClassFunctionContains:
                {
                    var code = String.Concat(pseudoClassFunctionContains, "(", attrValue, ")");
                    Insert(SimpleSelector.PseudoClass(el => el.TextContent.Contains(attrValue), code));
                    return(true);
                }

                default:
                    return(true);
                }
            }

            return(false);
        }
Example #20
0
        /// <summary>
        /// Invoked once a colon with a function has been found in the token enumerator.
        /// </summary>
        /// <param name="tokens">The token source.</param>
        /// <returns>The created selector.</returns>
        public SimpleSelector GetPseudoClassFunction(IEnumerator <CssToken> tokens)
        {
            var name = ((CssKeywordToken)tokens.Current).Data;
            var args = new List <CssToken>();

            while (tokens.MoveNext())
            {
                if (tokens.Current.Type == CssTokenType.RoundBracketClose)
                {
                    break;
                }
                else
                {
                    args.Add(tokens.Current);
                }
            }

            if (args.Count == 0)
            {
                return(null);
            }

            switch (name)
            {
            case PSEUDOCLASSFUNCTION_NTHCHILD:
                return(GetArguments <NthChildSelector>(args.GetEnumerator()));

            case PSEUDOCLASSFUNCTION_NTHLASTCHILD:
                return(GetArguments <NthLastChildSelector>(args.GetEnumerator()));

            case PSEUDOCLASSFUNCTION_DIR:
                if (args.Count == 1 && args[0].Type == CssTokenType.Ident)
                {
                    var dir     = ((CssKeywordToken)args[0]).Data;
                    var code    = string.Format("{0}({1})", PSEUDOCLASSFUNCTION_DIR, dir);
                    var dirCode = dir == "ltr" ? DirectionMode.Ltr : DirectionMode.Rtl;
                    return(SimpleSelector.PseudoClass(el => el.Dir == dirCode, code));
                }

                break;

            case PSEUDOCLASSFUNCTION_LANG:
                if (args.Count == 1 && args[0].Type == CssTokenType.Ident)
                {
                    var lang = ((CssKeywordToken)args[0]).Data;
                    var code = string.Format("{0}({1})", PSEUDOCLASSFUNCTION_LANG, lang);
                    return(SimpleSelector.PseudoClass(el => el.Lang.Equals(lang, StringComparison.OrdinalIgnoreCase), code));
                }

                break;

            case PSEUDOCLASSFUNCTION_CONTAINS:
                if (args.Count == 1 && args[0].Type == CssTokenType.String)
                {
                    var str  = ((CssStringToken)args[0]).Data;
                    var code = string.Format("{0}({1})", PSEUDOCLASSFUNCTION_CONTAINS, str);
                    return(SimpleSelector.PseudoClass(el => el.TextContent.Contains(str), code));
                }
                else if (args.Count == 1 && args[0].Type == CssTokenType.Ident)
                {
                    var str  = ((CssKeywordToken)args[0]).Data;
                    var code = string.Format("{0}({1})", PSEUDOCLASSFUNCTION_CONTAINS, str);
                    return(SimpleSelector.PseudoClass(el => el.TextContent.Contains(str), code));
                }

                break;

            case PSEUDOCLASSFUNCTION_NOT:
            {
                var sel = GetSimpleSelector(args.GetEnumerator());
                if (sel != null)
                {
                    var code = string.Format("{0}({1})", PSEUDOCLASSFUNCTION_NOT, sel.ToCss());
                    return(SimpleSelector.PseudoClass(el => !sel.Match(el), code));
                }
            }
            break;
            }

            if (!ignoreErrors)
            {
                throw new DOMException(ErrorCode.SyntaxError);
            }

            return(null);
        }