mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:17:36 +00:00
LibWeb: Implement the :open and :closed pseudo-classes
These apply to any elements that have some kind of open/closed state. The spec suggests `<details>`, `<dialog>`, and `<select>`, so that's what I've supported here. Only `<details>` is fleshed out right now, but once the others are, these pseudo-classes should work automatically. :^)
This commit is contained in:
parent
29bb0f0ae6
commit
6bf107fc16
4 changed files with 64 additions and 0 deletions
18
Tests/LibWeb/Ref/css-open-closed-selectors.html
Normal file
18
Tests/LibWeb/Ref/css-open-closed-selectors.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<!doctype html>
|
||||||
|
<link rel="match" href="reference/css-open-closed-selectors-ref.html" />
|
||||||
|
<style>
|
||||||
|
:open {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
:closed {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<details open>
|
||||||
|
<summary>Hi</summary>
|
||||||
|
Well hello friends!
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Hi</summary>
|
||||||
|
Well hello friends!
|
||||||
|
</details>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!doctype html>
|
||||||
|
<style>
|
||||||
|
.open {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
.closed {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<details open class="open">
|
||||||
|
<summary>Hi</summary>
|
||||||
|
Well hello friends!
|
||||||
|
</details>
|
||||||
|
<details class="closed">
|
||||||
|
<summary>Hi</summary>
|
||||||
|
Well hello friends!
|
||||||
|
</details>
|
|
@ -11,6 +11,9 @@
|
||||||
"checked": {
|
"checked": {
|
||||||
"argument": ""
|
"argument": ""
|
||||||
},
|
},
|
||||||
|
"closed": {
|
||||||
|
"argument": ""
|
||||||
|
},
|
||||||
"defined": {
|
"defined": {
|
||||||
"argument": ""
|
"argument": ""
|
||||||
},
|
},
|
||||||
|
@ -92,6 +95,9 @@
|
||||||
"only-of-type": {
|
"only-of-type": {
|
||||||
"argument": ""
|
"argument": ""
|
||||||
},
|
},
|
||||||
|
"open": {
|
||||||
|
"argument": ""
|
||||||
|
},
|
||||||
"paused": {
|
"paused": {
|
||||||
"argument": ""
|
"argument": ""
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
#include <LibWeb/HTML/HTMLAnchorElement.h>
|
||||||
#include <LibWeb/HTML/HTMLAreaElement.h>
|
#include <LibWeb/HTML/HTMLAreaElement.h>
|
||||||
#include <LibWeb/HTML/HTMLButtonElement.h>
|
#include <LibWeb/HTML/HTMLButtonElement.h>
|
||||||
|
#include <LibWeb/HTML/HTMLDetailsElement.h>
|
||||||
|
#include <LibWeb/HTML/HTMLDialogElement.h>
|
||||||
#include <LibWeb/HTML/HTMLFieldSetElement.h>
|
#include <LibWeb/HTML/HTMLFieldSetElement.h>
|
||||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||||
|
@ -238,6 +240,24 @@ static bool matches_read_write_pseudo_class(DOM::Element const& element)
|
||||||
return element.is_editable();
|
return element.is_editable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/selectors-4/#open-state
|
||||||
|
static bool matches_open_state_pseudo_class(DOM::Element const& element, bool open)
|
||||||
|
{
|
||||||
|
// The :open pseudo-class represents an element that has both “open” and “closed” states,
|
||||||
|
// and which is currently in the “open” state.
|
||||||
|
// The :closed pseudo-class represents an element that has both “open” and “closed” states,
|
||||||
|
// and which is currently in the closed state.
|
||||||
|
|
||||||
|
// NOTE: Spec specifically suggests supporting <details>, <dialog>, and <select>.
|
||||||
|
// There may be others we want to treat as open or closed.
|
||||||
|
if (is<HTML::HTMLDetailsElement>(element) || is<HTML::HTMLDialogElement>(element))
|
||||||
|
return open == element.has_attribute(HTML::AttributeNames::open);
|
||||||
|
if (is<HTML::HTMLSelectElement>(element))
|
||||||
|
return open == static_cast<HTML::HTMLSelectElement const&>(element).is_open();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClassSelector const& pseudo_class, Optional<CSS::CSSStyleSheet const&> style_sheet_for_rule, DOM::Element const& element, JS::GCPtr<DOM::ParentNode const> scope)
|
static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClassSelector const& pseudo_class, Optional<CSS::CSSStyleSheet const&> style_sheet_for_rule, DOM::Element const& element, JS::GCPtr<DOM::ParentNode const> scope)
|
||||||
{
|
{
|
||||||
switch (pseudo_class.type) {
|
switch (pseudo_class.type) {
|
||||||
|
@ -509,6 +529,9 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
||||||
// - FIXME: textarea elements that have a placeholder attribute whose value is currently being presented to the user.
|
// - FIXME: textarea elements that have a placeholder attribute whose value is currently being presented to the user.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case CSS::PseudoClass::Open:
|
||||||
|
case CSS::PseudoClass::Closed:
|
||||||
|
return matches_open_state_pseudo_class(element, pseudo_class.type == CSS::PseudoClass::Open);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue