mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:18:13 +00:00
LibHTML: Implement basic :hover pseudo-class support
This is currently very aggressive. Whenever the Document's hovered node changes, we invalidate all style and do a full relayout. It does look cool though. So cool that I'm adding it to the default stylesheet. :^)
This commit is contained in:
parent
605a225b53
commit
61ef17b87a
6 changed files with 52 additions and 1 deletions
13
Base/home/anon/www/hover.html
Normal file
13
Base/home/anon/www/hover.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Hover test!</title>
|
||||||
|
<style>
|
||||||
|
a:hover {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="hover.html">this is a link</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -32,6 +32,7 @@ h1 {
|
||||||
<li><a href="link.html">link element</a></li>
|
<li><a href="link.html">link element</a></li>
|
||||||
<li><a href="blink.html">blink element</a></li>
|
<li><a href="blink.html">blink element</a></li>
|
||||||
<li><a href="br.html">br element</a></li>
|
<li><a href="br.html">br element</a></li>
|
||||||
|
<li><a href="hover.html">hover element</a></li>
|
||||||
<li><a href="http://www.serenityos.org/">www.serenityos.org</a></li>
|
<li><a href="http://www.serenityos.org/">www.serenityos.org</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -90,6 +90,10 @@ a {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin-top: 4;
|
margin-top: 4;
|
||||||
margin-bottom: 4;
|
margin-bottom: 4;
|
||||||
|
|
|
@ -1,10 +1,33 @@
|
||||||
#include <LibHTML/CSS/SelectorEngine.h>
|
#include <LibHTML/CSS/SelectorEngine.h>
|
||||||
|
#include <LibHTML/DOM/Document.h>
|
||||||
#include <LibHTML/DOM/Element.h>
|
#include <LibHTML/DOM/Element.h>
|
||||||
|
|
||||||
namespace SelectorEngine {
|
namespace SelectorEngine {
|
||||||
|
|
||||||
|
static bool matches_hover_pseudo_class(const Element& element)
|
||||||
|
{
|
||||||
|
auto* hovered_node = element.document().hovered_node();
|
||||||
|
if (!hovered_node)
|
||||||
|
return false;
|
||||||
|
if (&element == hovered_node)
|
||||||
|
return true;
|
||||||
|
return element.is_ancestor_of(*hovered_node);
|
||||||
|
}
|
||||||
|
|
||||||
bool matches(const Selector::Component& component, const Element& element)
|
bool matches(const Selector::Component& component, const Element& element)
|
||||||
{
|
{
|
||||||
|
switch (component.pseudo_class) {
|
||||||
|
case Selector::Component::PseudoClass::None:
|
||||||
|
break;
|
||||||
|
case Selector::Component::PseudoClass::Link:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
break;
|
||||||
|
case Selector::Component::PseudoClass::Hover:
|
||||||
|
if (!matches_hover_pseudo_class(element))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (component.type) {
|
switch (component.type) {
|
||||||
case Selector::Component::Type::Id:
|
case Selector::Component::Type::Id:
|
||||||
return component.value == element.attribute("id");
|
return component.value == element.attribute("id");
|
||||||
|
|
|
@ -195,3 +195,13 @@ const LayoutDocument* Document::layout_node() const
|
||||||
{
|
{
|
||||||
return static_cast<const LayoutDocument*>(Node::layout_node());
|
return static_cast<const LayoutDocument*>(Node::layout_node());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::set_hovered_node(Node* node)
|
||||||
|
{
|
||||||
|
if (m_hovered_node == node)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_hovered_node = node;
|
||||||
|
invalidate_style();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
|
|
||||||
virtual String tag_name() const override { return "#document"; }
|
virtual String tag_name() const override { return "#document"; }
|
||||||
|
|
||||||
void set_hovered_node(Node* node) { m_hovered_node = node; }
|
void set_hovered_node(Node*);
|
||||||
Node* hovered_node() { return m_hovered_node; }
|
Node* hovered_node() { return m_hovered_node; }
|
||||||
const Node* hovered_node() const { return m_hovered_node; }
|
const Node* hovered_node() const { return m_hovered_node; }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue