Skip to main content

script/dom/
intersectionobserverentry.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use js::rust::HandleObject;
10use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto_and_cx};
11
12use super::bindings::codegen::Bindings::IntersectionObserverEntryBinding::{
13    IntersectionObserverEntryInit, IntersectionObserverEntryMethods,
14};
15use super::bindings::num::Finite;
16use crate::dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::DOMRectInit;
17use crate::dom::bindings::root::{Dom, DomRoot};
18use crate::dom::domrectreadonly::DOMRectReadOnly;
19use crate::dom::element::Element;
20use crate::dom::window::Window;
21/// An individual IntersectionObserver entry.
22///
23/// <https://w3c.github.io/IntersectionObserver/#intersection-observer-entry>
24#[dom_struct]
25pub(crate) struct IntersectionObserverEntry {
26    reflector_: Reflector,
27    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-time>
28    time: Cell<Finite<f64>>,
29    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-rootbounds>
30    root_bounds: Option<Dom<DOMRectReadOnly>>,
31    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-boundingclientrect>
32    bounding_client_rect: Dom<DOMRectReadOnly>,
33    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionrect>
34    intersection_rect: Dom<DOMRectReadOnly>,
35    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-isintersecting>
36    is_intersecting: Cell<bool>,
37    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-isvisible>
38    is_visible: Cell<bool>,
39    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionratio>
40    intersection_ratio: Cell<Finite<f64>>,
41    // <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-target>
42    target: Dom<Element>,
43}
44
45impl IntersectionObserverEntry {
46    #[allow(clippy::too_many_arguments)]
47    fn new_inherited(
48        time: Finite<f64>,
49        root_bounds: Option<&DOMRectReadOnly>,
50        bounding_client_rect: &DOMRectReadOnly,
51        intersection_rect: &DOMRectReadOnly,
52        is_intersecting: bool,
53        is_visible: bool,
54        intersection_ratio: Finite<f64>,
55        target: &Element,
56    ) -> Self {
57        Self {
58            reflector_: Reflector::new(),
59            target: Dom::from_ref(target),
60            time: Cell::new(time),
61            root_bounds: root_bounds.map(Dom::from_ref),
62            bounding_client_rect: Dom::from_ref(bounding_client_rect),
63            intersection_rect: Dom::from_ref(intersection_rect),
64            is_intersecting: Cell::new(is_intersecting),
65            is_visible: Cell::new(is_visible),
66            intersection_ratio: Cell::new(intersection_ratio),
67        }
68    }
69
70    #[allow(clippy::too_many_arguments)]
71    pub(crate) fn new(
72        cx: &mut JSContext,
73        window: &Window,
74        proto: Option<HandleObject>,
75        time: Finite<f64>,
76        root_bounds: Option<&DOMRectReadOnly>,
77        bounding_client_rect: &DOMRectReadOnly,
78        intersection_rect: &DOMRectReadOnly,
79        is_intersecting: bool,
80        is_visible: bool,
81        intersection_ratio: Finite<f64>,
82        target: &Element,
83    ) -> DomRoot<Self> {
84        let observer = Box::new(Self::new_inherited(
85            time,
86            root_bounds,
87            bounding_client_rect,
88            intersection_rect,
89            is_intersecting,
90            is_visible,
91            intersection_ratio,
92            target,
93        ));
94        reflect_dom_object_with_proto_and_cx(observer, window, proto, cx)
95    }
96
97    fn new_from_dictionary(
98        cx: &mut JSContext,
99        window: &Window,
100        proto: Option<HandleObject>,
101        init: &IntersectionObserverEntryInit,
102    ) -> DomRoot<Self> {
103        let mut domrectreadonly_from_dictionary = |dictionary: &DOMRectInit| {
104            DOMRectReadOnly::new_from_dictionary(cx, window.as_global_scope(), proto, dictionary)
105        };
106        let observer = Box::new(Self::new_inherited(
107            init.time,
108            Some(&*domrectreadonly_from_dictionary(&init.rootBounds)),
109            &domrectreadonly_from_dictionary(&init.boundingClientRect),
110            &domrectreadonly_from_dictionary(&init.intersectionRect),
111            init.isIntersecting,
112            init.isVisible,
113            init.intersectionRatio,
114            &init.target,
115        ));
116        reflect_dom_object_with_proto_and_cx(observer, window, proto, cx)
117    }
118}
119
120impl IntersectionObserverEntryMethods<crate::DomTypeHolder> for IntersectionObserverEntry {
121    /// > The attribute must return a DOMHighResTimeStamp that corresponds to the time the
122    /// > intersection was recorded, relative to the time origin of the global object
123    /// > associated with the IntersectionObserver instance that generated the notification.
124    ///
125    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-time>
126    fn Time(&self) -> Finite<f64> {
127        self.time.get()
128    }
129
130    /// > For a same-origin-domain target, this will be the root intersection rectangle.
131    /// > Otherwise, this will be null. Note that if the target is in a different browsing
132    /// > context than the intersection root, this will be in a different coordinate system
133    /// > than boundingClientRect and intersectionRect.
134    ///
135    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-rootbounds>
136    fn GetRootBounds(&self) -> Option<DomRoot<DOMRectReadOnly>> {
137        self.root_bounds.as_ref().map(|rect| rect.as_rooted())
138    }
139
140    /// > A DOMRectReadOnly obtained by getting the bounding box for target.
141    ///
142    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-boundingclientrect>
143    fn BoundingClientRect(&self) -> DomRoot<DOMRectReadOnly> {
144        self.bounding_client_rect.as_rooted()
145    }
146
147    /// > boundingClientRect, intersected by each of target's ancestors' clip rects (up to
148    /// > but not including root), intersected with the root intersection rectangle. This
149    /// > value represents the portion of target that intersects with the root intersection
150    /// > rectangle.
151    ///
152    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionrect>
153    fn IntersectionRect(&self) -> DomRoot<DOMRectReadOnly> {
154        self.intersection_rect.as_rooted()
155    }
156
157    /// > True if the target intersects with the root; false otherwise. This flag makes it
158    /// > possible to distinguish between an IntersectionObserverEntry signalling the
159    /// > transition from intersecting to not-intersecting; and an IntersectionObserverEntry
160    /// > signalling a transition from not-intersecting to intersecting with a zero-area
161    /// > intersection rect (as will happen with edge-adjacent intersections, or when the
162    /// > boundingClientRect has zero area).
163    ///
164    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-isintersecting>
165    fn IsIntersecting(&self) -> bool {
166        self.is_intersecting.get()
167    }
168
169    /// > Contains the result of running the visibility algorithm on target.
170    ///
171    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-isvisible>
172    fn IsVisible(&self) -> bool {
173        self.is_visible.get()
174    }
175
176    /// > If the boundingClientRect has non-zero area, this will be the ratio of
177    /// > intersectionRect area to boundingClientRect area. Otherwise, this will be 1 if the
178    /// > isIntersecting is true, and 0 if not.
179    ///
180    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionratio>
181    fn IntersectionRatio(&self) -> Finite<f64> {
182        self.intersection_ratio.get()
183    }
184
185    /// > The Element whose intersection with the intersection root changed.
186    ///
187    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-target>
188    fn Target(&self) -> DomRoot<Element> {
189        self.target.as_rooted()
190    }
191
192    /// <https://w3c.github.io/IntersectionObserver/#dom-intersectionobserverentry-intersectionobserverentry>
193    fn Constructor(
194        cx: &mut JSContext,
195        window: &Window,
196        proto: Option<HandleObject>,
197        init: &IntersectionObserverEntryInit,
198    ) -> DomRoot<IntersectionObserverEntry> {
199        Self::new_from_dictionary(cx, window, proto, init)
200    }
201}