/* * Copyright (c) 2021, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace Web::IntersectionObserver { using NullableIntersectionObserverRoot = Variant, GC::Root, Empty>; struct IntersectionObserverInit { NullableIntersectionObserverRoot root { Empty {} }; String root_margin { "0px"_string }; String scroll_margin { "0px"_string }; Variant> threshold { 0 }; long delay = 0; bool track_visibility = false; }; // https://w3c.github.io/IntersectionObserver/#intersection-observer-interface class IntersectionObserver final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(IntersectionObserver, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(IntersectionObserver); public: static constexpr bool OVERRIDES_FINALIZE = true; static WebIDL::ExceptionOr> construct_impl(JS::Realm&, GC::Ptr callback, IntersectionObserverInit const& options = {}); virtual ~IntersectionObserver() override; void observe(DOM::Element& target); void unobserve(DOM::Element& target); void disconnect(); Vector> take_records(); Vector> const& observation_targets() const { return m_observation_targets; } NullableIntersectionObserverRoot root() const; String root_margin() const; String scroll_margin() const; Vector const& scroll_margin_values() const { return m_scroll_margin; } Vector const& thresholds() const { return m_thresholds; } long delay() const { return m_delay; } bool track_visibility() const { return m_track_visibility; } Variant, GC::Root> intersection_root() const; GC::Ref intersection_root_node() const; bool is_implicit_root() const { return !m_root; } CSSPixelRect root_intersection_rectangle() const; void queue_entry(Badge, GC::Ref); WebIDL::CallbackType& callback() { return *m_callback; } private: explicit IntersectionObserver(JS::Realm&, GC::Ptr callback, NullableIntersectionObserverRoot const& root, Vector root_margin, Vector scroll_margin, Vector&& thresholds, double debug, bool track_visibility); virtual void initialize(JS::Realm&) override; virtual void visit_edges(JS::Cell::Visitor&) override; virtual void finalize() override; static Optional> parse_a_margin(JS::Realm&, String); // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-callback-slot GC::Ptr m_callback; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-root GC::Ptr m_root; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-rootmargin Vector m_root_margin; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-scrollmargin Vector m_scroll_margin; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-thresholds Vector m_thresholds; // https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-delay long m_delay; // https://w3c.github.io/IntersectionObserver/#dom-intersectionobserver-trackvisibility bool m_track_visibility; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-queuedentries-slot Vector> m_queued_entries; // https://www.w3.org/TR/intersection-observer/#dom-intersectionobserver-observationtargets-slot Vector> m_observation_targets; // AD-HOC: This is the document where we've registered the IntersectionObserver. GC::Weak m_document; }; }