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