Add the onvisible event handler to Element (#2911)
* Add the `onvisible` event using the IntersectionObserver * Add a visible example This example is based on https://codepen.io/ryanfinni/pen/VwZeGxN * Remove web-sys CustomEvent feature for html package * update js bindings and hash * Use dioxus doc instead of lorem ipsum * Fix clippy warning * Add get_target method to the event data * Make `get_time` return an Instant instead of a f64 * fix merge conflicts, compilinga * remove target * small nits * serialzie as time_ms * fix timing, works on desktop * remove latent nits, fix hash * box size clippy * fix browserlist cargo.lock --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com> Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
20 files changed
+961
-289
No files matched your search
@@ -20,6 +20,7 @@ export class BaseInterpreter {
|
||||
root: HTMLElement;
|
||||
handler: EventListener;
|
||||
resizeObserver: ResizeObserver;
|
||||
intersectionObserver: IntersectionObserver;
|
||||
|
||||
nodes: Node[];
|
||||
stack: Node[];
|
||||
@@ -55,7 +56,7 @@ export class BaseInterpreter {
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
|
||||
createObserver(element: HTMLElement) {
|
||||
createResizeObserver(element: HTMLElement) {
|
||||
// Lazily create the resize observer
|
||||
if (!this.resizeObserver) {
|
||||
this.resizeObserver = new ResizeObserver((entries) => {
|
||||
@@ -67,13 +68,48 @@ export class BaseInterpreter {
|
||||
this.resizeObserver.observe(element);
|
||||
}
|
||||
|
||||
removeObserver(element: HTMLElement) {
|
||||
removeResizeObserver(element: HTMLElement) {
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.unobserve(element);
|
||||
}
|
||||
}
|
||||
|
||||
handleIntersectionEvent(entry: IntersectionObserverEntry) {
|
||||
const target = entry.target;
|
||||
|
||||
let event = new CustomEvent<IntersectionObserverEntry>("visible", {
|
||||
bubbles: false,
|
||||
detail: entry,
|
||||
});
|
||||
|
||||
target.dispatchEvent(event);
|
||||
}
|
||||
|
||||
createIntersectionObserver(element: HTMLElement) {
|
||||
/// Lazily create the intersection observer
|
||||
if (!this.intersectionObserver) {
|
||||
this.intersectionObserver = new IntersectionObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
this.handleIntersectionEvent(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.intersectionObserver.observe(element);
|
||||
}
|
||||
|
||||
removeIntersectionObserver(element: HTMLElement) {
|
||||
if (this.intersectionObserver) {
|
||||
this.intersectionObserver.unobserve(element);
|
||||
}
|
||||
}
|
||||
|
||||
createListener(event_name: string, element: HTMLElement, bubbles: boolean) {
|
||||
if (event_name == "resize") {
|
||||
this.createResizeObserver(element);
|
||||
} else if (event_name == "visible") {
|
||||
this.createIntersectionObserver(element);
|
||||
}
|
||||
|
||||
if (bubbles) {
|
||||
if (this.global[event_name] === undefined) {
|
||||
this.global[event_name] = { active: 1, callback: this.handler };
|
||||
@@ -88,14 +124,14 @@ export class BaseInterpreter {
|
||||
}
|
||||
element.addEventListener(event_name, this.handler);
|
||||
}
|
||||
|
||||
if (event_name == "resize") {
|
||||
this.createObserver(element);
|
||||
}
|
||||
}
|
||||
|
||||
removeListener(element: HTMLElement, event_name: string, bubbles: boolean) {
|
||||
if (bubbles) {
|
||||
if (event_name == "resize") {
|
||||
this.removeResizeObserver(element);
|
||||
} else if (event_name == "visible") {
|
||||
this.removeIntersectionObserver(element);
|
||||
} else if (bubbles) {
|
||||
this.removeBubblingListener(event_name);
|
||||
} else {
|
||||
this.removeNonBubblingListener(element, event_name);
|
||||
|
||||
@@ -62,6 +62,8 @@ export function serializeEvent(
|
||||
const detail = event.detail;
|
||||
if (detail instanceof ResizeObserverEntry) {
|
||||
extend(serializeResizeEventDetail(detail));
|
||||
} else if (detail instanceof IntersectionObserverEntry) {
|
||||
extend(serializeIntersectionEventDetail(detail));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,21 +131,36 @@ export function serializeResizeEventDetail(
|
||||
border_box_size:
|
||||
detail.borderBoxSize !== undefined
|
||||
? toSerializableResizeObserverSize(
|
||||
detail.borderBoxSize[0],
|
||||
is_inline_width
|
||||
)
|
||||
detail.borderBoxSize[0],
|
||||
is_inline_width
|
||||
)
|
||||
: detail.contentRect,
|
||||
content_box_size:
|
||||
detail.contentBoxSize !== undefined
|
||||
? toSerializableResizeObserverSize(
|
||||
detail.contentBoxSize[0],
|
||||
is_inline_width
|
||||
)
|
||||
detail.contentBoxSize[0],
|
||||
is_inline_width
|
||||
)
|
||||
: detail.contentRect,
|
||||
content_rect: detail.contentRect,
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeIntersectionEventDetail(
|
||||
detail: IntersectionObserverEntry): SerializedEvent {
|
||||
return {
|
||||
bounding_client_rect: detail.boundingClientRect,
|
||||
intersection_ratio: detail.intersectionRatio,
|
||||
intersection_rect: detail.intersectionRect,
|
||||
is_intersecting: detail.isIntersecting,
|
||||
root_bounds: detail.rootBounds,
|
||||
|
||||
// math.floor removes the floating point extra such that we serialize into integer
|
||||
// this *might* become an issue longer term
|
||||
time_ms: Math.floor(Date.now() + detail.time),
|
||||
}
|
||||
}
|
||||
|
||||
function serializeInputEvent(
|
||||
event: InputEvent,
|
||||
target: EventTarget
|
||||
|
||||
Reference in new issue
Block a user