mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:27:35 +00:00
LibWeb: Support :active pseudo-class for hyperlinks, :focus possibly
Adds support for the :active pseudo-class for hyperlinks (<a> tags only). Also, since it was very similar to :focus and an element having a focused state was already implemented, I went ahead and implemented that pseudo-class too, although I cannot come up with a working example to validate it.
This commit is contained in:
parent
457edaa4d2
commit
5eb65286b6
10 changed files with 39 additions and 2 deletions
|
@ -563,6 +563,8 @@ public:
|
|||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link;
|
||||
} else if (pseudo_name.equals_ignoring_case("visited")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited;
|
||||
} else if (pseudo_name.equals_ignoring_case("active")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active;
|
||||
} else if (pseudo_name.equals_ignoring_case("hover")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover;
|
||||
} else if (pseudo_name.equals_ignoring_case("focus")) {
|
||||
|
|
|
@ -200,6 +200,8 @@ Vector<CSS::Selector::ComplexSelector> Parser::parse_selectors(Vector<String> pa
|
|||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Link;
|
||||
} else if (pseudo_name.equals_ignoring_case("visited")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Visited;
|
||||
} else if (pseudo_name.equals_ignoring_case("active")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Active;
|
||||
} else if (pseudo_name.equals_ignoring_case("hover")) {
|
||||
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Hover;
|
||||
} else if (pseudo_name.equals_ignoring_case("focus")) {
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
Enabled,
|
||||
Checked,
|
||||
Not,
|
||||
Active,
|
||||
};
|
||||
PseudoClass pseudo_class { PseudoClass::None };
|
||||
|
||||
|
|
|
@ -44,13 +44,18 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E
|
|||
case CSS::Selector::SimpleSelector::PseudoClass::Visited:
|
||||
// FIXME: Maybe match this selector sometimes?
|
||||
return false;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Active:
|
||||
if (!element.is_active())
|
||||
return false;
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Hover:
|
||||
if (!matches_hover_pseudo_class(element))
|
||||
return false;
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Focus:
|
||||
// FIXME: Implement matches_focus_pseudo_class(element)
|
||||
if (!element.is_focused())
|
||||
return false;
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::FirstChild:
|
||||
if (element.previous_element_sibling())
|
||||
return false;
|
||||
|
|
|
@ -876,6 +876,17 @@ void Document::set_focused_element(Element* element)
|
|||
m_layout_root->set_needs_display();
|
||||
}
|
||||
|
||||
void Document::set_active_element(Element* element)
|
||||
{
|
||||
if (m_active_element == element)
|
||||
return;
|
||||
|
||||
m_active_element = element;
|
||||
|
||||
if (m_layout_root)
|
||||
m_layout_root->set_needs_display();
|
||||
}
|
||||
|
||||
void Document::set_ready_state(const String& ready_state)
|
||||
{
|
||||
m_ready_state = ready_state;
|
||||
|
|
|
@ -208,6 +208,10 @@ public:
|
|||
|
||||
void set_focused_element(Element*);
|
||||
|
||||
const Element* active_element() const { return m_active_element; }
|
||||
|
||||
void set_active_element(Element*);
|
||||
|
||||
bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; }
|
||||
void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; }
|
||||
|
||||
|
@ -323,6 +327,7 @@ private:
|
|||
bool m_editable { false };
|
||||
|
||||
WeakPtr<Element> m_focused_element;
|
||||
WeakPtr<Element> m_active_element;
|
||||
|
||||
bool m_created_for_appropriate_template_contents { false };
|
||||
RefPtr<Document> m_associated_inert_template_document;
|
||||
|
|
|
@ -327,6 +327,11 @@ bool Element::is_focused() const
|
|||
return document().focused_element() == this;
|
||||
}
|
||||
|
||||
bool Element::is_active() const
|
||||
{
|
||||
return document().active_element() == this;
|
||||
}
|
||||
|
||||
NonnullRefPtr<HTMLCollection> Element::get_elements_by_tag_name(FlyString const& tag_name)
|
||||
{
|
||||
// FIXME: Support "*" for tag_name
|
||||
|
|
|
@ -86,6 +86,8 @@ public:
|
|||
bool is_focused() const;
|
||||
virtual bool is_focusable() const { return false; }
|
||||
|
||||
bool is_active() const;
|
||||
|
||||
NonnullRefPtr<HTMLCollection> get_elements_by_tag_name(FlyString const&);
|
||||
NonnullRefPtr<HTMLCollection> get_elements_by_class_name(FlyString const&);
|
||||
|
||||
|
|
|
@ -341,6 +341,9 @@ void dump_selector(StringBuilder& builder, const CSS::Selector& selector)
|
|||
case CSS::Selector::SimpleSelector::PseudoClass::Visited:
|
||||
pseudo_class_description = "Visited";
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Active:
|
||||
pseudo_class_description = "Active";
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::None:
|
||||
pseudo_class_description = "None";
|
||||
break;
|
||||
|
|
|
@ -237,6 +237,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt
|
|||
auto anchor = href.substring_view(1, href.length() - 1);
|
||||
m_frame.scroll_to_anchor(anchor);
|
||||
} else {
|
||||
document->set_active_element(link);
|
||||
if (m_frame.is_top_level()) {
|
||||
if (auto* page = m_frame.page())
|
||||
page->client().page_did_click_link(url, link->target(), modifiers);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue