mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-30 20:59:16 +00:00
LibWeb: Implement Element::check_visibility
This commit is contained in:
parent
4a2d5bcf89
commit
5f154ba372
Notes:
github-actions[bot]
2024-07-20 08:15:46 +00:00
Author: https://github.com/EdwinHoksberg
Commit: 5f154ba372
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/717
Reviewed-by: https://github.com/tcl3 ✅
5 changed files with 148 additions and 1 deletions
|
@ -0,0 +1,8 @@
|
||||||
|
display-none visible: false
|
||||||
|
content-visibility-parent visible: true
|
||||||
|
content-visibility-child visible: false
|
||||||
|
opacity-hidden visible: false
|
||||||
|
opacity-visible visible: true
|
||||||
|
visibility-hidden visible: false
|
||||||
|
visibility-visible visible: true
|
||||||
|
content-visibility-auto-hidden visible: true
|
71
Tests/LibWeb/Text/input/HTML/Element-checkVisibility.html
Normal file
71
Tests/LibWeb/Text/input/HTML/Element-checkVisibility.html
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
.display-none {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-visibility-parent {
|
||||||
|
content-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.opacity-visible {
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visibility-hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.visibility-visible {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-visibility-auto-hidden {
|
||||||
|
content-visibility: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="display-none"></div>
|
||||||
|
|
||||||
|
<div class="content-visibility-parent">
|
||||||
|
<div class="content-visibility-child"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="opacity-hidden"></div>
|
||||||
|
<div class="opacity-visible"></div>
|
||||||
|
|
||||||
|
<div class="visibility-hidden"></div>
|
||||||
|
<div class="visibility-visible"></div>
|
||||||
|
|
||||||
|
<div class="content-visibility-auto-hidden"></div>
|
||||||
|
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<script>
|
||||||
|
test(() => {
|
||||||
|
const displayNone = document.querySelector('.display-none');
|
||||||
|
println("display-none visible: " + displayNone.checkVisibility());
|
||||||
|
|
||||||
|
const contentVisibilityParent = document.querySelector('.content-visibility-parent');
|
||||||
|
println("content-visibility-parent visible: " + contentVisibilityParent.checkVisibility());
|
||||||
|
|
||||||
|
const contentVisibilityChild = document.querySelector('.content-visibility-child');
|
||||||
|
println("content-visibility-child visible: " + contentVisibilityChild.checkVisibility());
|
||||||
|
|
||||||
|
const opacityHidden = document.querySelector('.opacity-hidden');
|
||||||
|
println("opacity-hidden visible: " + opacityHidden.checkVisibility({opacityProperty: true}));
|
||||||
|
|
||||||
|
const opacityVisible = document.querySelector('.opacity-visible');
|
||||||
|
println("opacity-visible visible: " + opacityVisible.checkVisibility({opacityProperty: true}));
|
||||||
|
|
||||||
|
const visibilityHidden = document.querySelector('.visibility-hidden');
|
||||||
|
println("visibility-hidden visible: " + visibilityHidden.checkVisibility({visibilityProperty: true}));
|
||||||
|
|
||||||
|
const visibilityVisible = document.querySelector('.visibility-visible');
|
||||||
|
println("visibility-visible visible: " + visibilityVisible.checkVisibility({visibilityProperty: true}));
|
||||||
|
|
||||||
|
const contentVisibilityAutoHidden = document.querySelector('.content-visibility-auto-hidden');
|
||||||
|
println("content-visibility-auto-hidden visible: " + contentVisibilityAutoHidden.checkVisibility({contentVisibilityAuto: true}));
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -2344,6 +2344,54 @@ void Element::scroll_by(HTML::ScrollToOptions options)
|
||||||
scroll(options);
|
scroll(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/cssom-view-1/#dom-element-checkvisibility
|
||||||
|
bool Element::check_visibility(Optional<CheckVisibilityOptions> options)
|
||||||
|
{
|
||||||
|
// NOTE: Ensure that layout is up-to-date before looking at metrics.
|
||||||
|
document().update_layout();
|
||||||
|
|
||||||
|
// 1. If this does not have an associated box, return false.
|
||||||
|
if (!paintable_box())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2. If an ancestor of this in the flat tree has content-visibility: hidden, return false.
|
||||||
|
for (auto* element = parent_element(); element; element = element->parent_element()) {
|
||||||
|
if (element->computed_css_values()->content_visibility() == CSS::ContentVisibility::Hidden)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AD-HOC: Since the rest of the steps use the options, we can return early if we haven't been given any options.
|
||||||
|
if (!options.has_value())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 3. If either the opacityProperty or the checkOpacity dictionary members of options are true, and this, or an ancestor of this in the flat tree, has a computed opacity value of 0, return false.
|
||||||
|
if (options->opacity_property || options->check_opacity) {
|
||||||
|
for (auto* element = this; element; element = element->parent_element()) {
|
||||||
|
if (element->computed_css_values()->opacity() == 0.0f)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. If either the visibilityProperty or the checkVisibilityCSS dictionary members of options are true, and this is invisible, return false.
|
||||||
|
if (options->visibility_property || options->check_visibility_css) {
|
||||||
|
if (computed_css_values()->visibility() == CSS::Visibility::Hidden)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. If the contentVisibilityAuto dictionary member of options is true and an ancestor of this in the flat tree skips its contents due to content-visibility: auto, return false.
|
||||||
|
// FIXME: Currently we do not skip any content if content-visibility is auto: https://drafts.csswg.org/css-contain-2/#proximity-to-the-viewport
|
||||||
|
auto const skipped_contents_due_to_content_visibility_auto = false;
|
||||||
|
if (options->content_visibility_auto && skipped_contents_due_to_content_visibility_auto) {
|
||||||
|
for (auto* element = this; element; element = element->parent_element()) {
|
||||||
|
if (element->computed_css_values()->content_visibility() == CSS::ContentVisibility::Auto)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Return true.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Element::id_reference_exists(String const& id_reference) const
|
bool Element::id_reference_exists(String const& id_reference) const
|
||||||
{
|
{
|
||||||
return document().get_element_by_id(id_reference);
|
return document().get_element_by_id(id_reference);
|
||||||
|
|
|
@ -48,6 +48,15 @@ struct ScrollIntoViewOptions : public HTML::ScrollOptions {
|
||||||
Bindings::ScrollLogicalPosition inline_ { Bindings::ScrollLogicalPosition::Nearest };
|
Bindings::ScrollLogicalPosition inline_ { Bindings::ScrollLogicalPosition::Nearest };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/cssom-view-1/#dictdef-checkvisibilityoptions
|
||||||
|
struct CheckVisibilityOptions {
|
||||||
|
bool check_opacity = false;
|
||||||
|
bool check_visibility_css = false;
|
||||||
|
bool content_visibility_auto = false;
|
||||||
|
bool opacity_property = false;
|
||||||
|
bool visibility_property = false;
|
||||||
|
};
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/custom-elements.html#upgrade-reaction
|
// https://html.spec.whatwg.org/multipage/custom-elements.html#upgrade-reaction
|
||||||
// An upgrade reaction, which will upgrade the custom element and contains a custom element definition; or
|
// An upgrade reaction, which will upgrade the custom element and contains a custom element definition; or
|
||||||
struct CustomElementUpgradeReaction {
|
struct CustomElementUpgradeReaction {
|
||||||
|
@ -354,6 +363,8 @@ public:
|
||||||
void scroll_by(HTML::ScrollToOptions);
|
void scroll_by(HTML::ScrollToOptions);
|
||||||
void scroll_by(double x, double y);
|
void scroll_by(double x, double y);
|
||||||
|
|
||||||
|
bool check_visibility(Optional<CheckVisibilityOptions>);
|
||||||
|
|
||||||
void register_intersection_observer(Badge<IntersectionObserver::IntersectionObserver>, IntersectionObserver::IntersectionObserverRegistration);
|
void register_intersection_observer(Badge<IntersectionObserver::IntersectionObserver>, IntersectionObserver::IntersectionObserverRegistration);
|
||||||
void unregister_intersection_observer(Badge<IntersectionObserver::IntersectionObserver>, JS::NonnullGCPtr<IntersectionObserver::IntersectionObserver>);
|
void unregister_intersection_observer(Badge<IntersectionObserver::IntersectionObserver>, JS::NonnullGCPtr<IntersectionObserver::IntersectionObserver>);
|
||||||
IntersectionObserver::IntersectionObserverRegistration& get_intersection_observer_registration(Badge<DOM::Document>, IntersectionObserver::IntersectionObserver const&);
|
IntersectionObserver::IntersectionObserverRegistration& get_intersection_observer_registration(Badge<DOM::Document>, IntersectionObserver::IntersectionObserver const&);
|
||||||
|
|
|
@ -20,6 +20,15 @@ dictionary ScrollIntoViewOptions : ScrollOptions {
|
||||||
ScrollLogicalPosition inline = "nearest";
|
ScrollLogicalPosition inline = "nearest";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/cssom-view-1/#dictdef-checkvisibilityoptions
|
||||||
|
dictionary CheckVisibilityOptions {
|
||||||
|
boolean checkOpacity = false;
|
||||||
|
boolean checkVisibilityCSS = false;
|
||||||
|
boolean contentVisibilityAuto = false;
|
||||||
|
boolean opacityProperty = false;
|
||||||
|
boolean visibilityProperty = false;
|
||||||
|
};
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#element
|
// https://dom.spec.whatwg.org/#element
|
||||||
[Exposed=Window]
|
[Exposed=Window]
|
||||||
interface Element : Node {
|
interface Element : Node {
|
||||||
|
@ -74,7 +83,7 @@ interface Element : Node {
|
||||||
DOMRectList getClientRects();
|
DOMRectList getClientRects();
|
||||||
DOMRect getBoundingClientRect();
|
DOMRect getBoundingClientRect();
|
||||||
|
|
||||||
[FIXME] boolean checkVisibility(optional CheckVisibilityOptions options = {});
|
boolean checkVisibility(optional CheckVisibilityOptions options = {});
|
||||||
|
|
||||||
undefined scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
|
undefined scrollIntoView(optional (boolean or ScrollIntoViewOptions) arg = {});
|
||||||
undefined scroll(optional ScrollToOptions options = {});
|
undefined scroll(optional ScrollToOptions options = {});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue