Skip to content

Commit 5922831

Browse files
authored
Merge pull request #8 from opensass/observer-fix
fix: update observer logic
2 parents 3cc7ec7 + 2d0d430 commit 5922831

File tree

2 files changed

+212
-4
lines changed

2 files changed

+212
-4
lines changed

src/leptos.rs

Lines changed: 212 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ use gloo_net::http::Request;
77
use leptos::callback::Callback;
88
use leptos::task::spawn_local;
99
use leptos::{html::*, prelude::*, *};
10-
use web_sys::RequestCache;
10+
use web_sys::IntersectionObserverEntry;
11+
use web_sys::js_sys;
12+
use web_sys::wasm_bindgen::JsCast;
13+
use web_sys::wasm_bindgen::closure::Closure;
14+
use web_sys::{IntersectionObserver, IntersectionObserverInit, RequestCache};
1115

1216
// Comment out aria attrs cause of: tachys-0.2.0/src/html/attribute/mod.rs:593:1:
1317
// not yet implemented: adding more than 26 attributes is not supported
@@ -141,6 +145,46 @@ pub fn Image(
141145
) -> impl IntoView {
142146
let (img_src, set_img_src) = signal(src);
143147

148+
Effect::new(move || {
149+
let callback = Closure::wrap(Box::new(
150+
move |entries: js_sys::Array, _observer: IntersectionObserver| {
151+
if let Some(entry) = entries.get(0).dyn_ref::<IntersectionObserverEntry>() {
152+
if entry.is_intersecting() {
153+
if let Some(node) = node_ref.get() {
154+
if let Some(img) = node.dyn_ref::<web_sys::HtmlImageElement>() {
155+
img.set_src(src);
156+
if let Some(cb) = on_load {
157+
cb.run(());
158+
}
159+
}
160+
}
161+
}
162+
}
163+
},
164+
)
165+
as Box<dyn FnMut(js_sys::Array, IntersectionObserver)>);
166+
167+
let options = IntersectionObserverInit::new();
168+
options.set_threshold(&js_sys::Array::of1(&0.1.into()));
169+
170+
let observer =
171+
IntersectionObserver::new_with_options(callback.as_ref().unchecked_ref(), &options)
172+
.expect("Failed to create IntersectionObserver");
173+
174+
if let Some(element) = node_ref.get() {
175+
if let Ok(img) = element.clone().dyn_into::<web_sys::HtmlElement>() {
176+
observer.observe(&img);
177+
}
178+
}
179+
180+
let observer_clone = observer.clone();
181+
let _cleanup = move || {
182+
observer_clone.disconnect();
183+
};
184+
185+
callback.forget();
186+
});
187+
144188
let onload = move |_| {
145189
if let Some(cb) = on_load {
146190
cb.run(());
@@ -247,6 +291,7 @@ pub fn Image(
247291
</span>
248292
}
249293
.into_any(),
294+
250295
Layout::Responsive => {
251296
let ratio = height.parse::<f64>().unwrap_or(1.0) / width.parse::<f64>().unwrap_or(1.0);
252297
let padding = format!("{}%", ratio * 100.0);
@@ -291,7 +336,55 @@ pub fn Image(
291336
}
292337
.into_any()
293338
}
294-
_ => view! {
339+
340+
Layout::Intrinsic => view! {
341+
<span style="display:inline-block; position:relative; max-width:100%;">
342+
<span style="max-width:100%;">
343+
<img
344+
node_ref=node_ref
345+
src=move || img_src.get()
346+
alt=alt
347+
class=class
348+
width=width
349+
height=height
350+
style=full_style.clone()
351+
sizes=sizes
352+
srcset=srcset
353+
decoding=decoding.as_str()
354+
crossorigin=crossorigin.as_str()
355+
referrerpolicy=referrerpolicy.as_str()
356+
loading=loading.as_str()
357+
fetchpriority=fetchpriority.as_str()
358+
aria_placeholder=placeholder
359+
on:load=onload
360+
on:error=onerror
361+
role="img"
362+
// aria-label=alt
363+
// aria-labelledby=aria_labelledby
364+
// aria-describedby=aria_describedby
365+
// aria-hidden=aria_hidden
366+
// aria-current=aria_current
367+
// aria-expanded=aria_expanded
368+
// aria-live=aria_live.as_str()
369+
// aria-pressed=aria_pressed.as_str()
370+
// aria-controls=aria_controls
371+
usemap=usemap
372+
ismap=ismap
373+
elementtiming=elementtiming
374+
attributionsrc=attributionsrc
375+
/>
376+
</span>
377+
<img
378+
src=blur_data_url
379+
style="display:none;"
380+
alt=alt
381+
aria-hidden="true"
382+
/>
383+
</span>
384+
}
385+
.into_any(),
386+
387+
Layout::Fixed => view! {
295388
<span style="display:inline-block; position:relative;">
296389
<img
297390
node_ref=node_ref
@@ -329,6 +422,123 @@ pub fn Image(
329422
</span>
330423
}
331424
.into_any(),
425+
426+
Layout::Auto => view! {
427+
<span style="display:inline-block; position:relative;">
428+
<img
429+
node_ref=node_ref
430+
src=move || img_src.get()
431+
alt=alt
432+
class=class
433+
width=width
434+
height=height
435+
style=full_style.clone()
436+
sizes=sizes
437+
srcset=srcset
438+
decoding=decoding.as_str()
439+
crossorigin=crossorigin.as_str()
440+
referrerpolicy=referrerpolicy.as_str()
441+
loading=loading.as_str()
442+
fetchpriority=fetchpriority.as_str()
443+
aria_placeholder=placeholder
444+
on:load=onload
445+
on:error=onerror
446+
role="img"
447+
// aria-label=alt
448+
// aria-labelledby=aria_labelledby
449+
// aria-describedby=aria_describedby
450+
// aria-hidden=aria_hidden
451+
// aria-current=aria_current
452+
// aria-expanded=aria_expanded
453+
// aria-live=aria_live.as_str()
454+
// aria-pressed=aria_pressed.as_str()
455+
// aria-controls=aria_controls
456+
usemap=usemap
457+
ismap=ismap
458+
elementtiming=elementtiming
459+
attributionsrc=attributionsrc
460+
/>
461+
</span>
462+
}
463+
.into_any(),
464+
465+
Layout::Stretch => view! {
466+
<span style="display:block; width:100%; height:100%; position:relative;">
467+
<img
468+
node_ref=node_ref
469+
src=move || img_src.get()
470+
alt=alt
471+
class=class
472+
width="100%"
473+
height="100%"
474+
style=full_style.clone()
475+
sizes=sizes
476+
srcset=srcset
477+
decoding=decoding.as_str()
478+
crossorigin=crossorigin.as_str()
479+
referrerpolicy=referrerpolicy.as_str()
480+
loading=loading.as_str()
481+
fetchpriority=fetchpriority.as_str()
482+
aria_placeholder=placeholder
483+
on:load=onload
484+
on:error=onerror
485+
role="img"
486+
// aria-label=alt
487+
// aria-labelledby=aria_labelledby
488+
// aria-describedby=aria_describedby
489+
// aria-hidden=aria_hidden
490+
// aria-current=aria_current
491+
// aria-expanded=aria_expanded
492+
// aria-live=aria_live.as_str()
493+
// aria-pressed=aria_pressed.as_str()
494+
// aria-controls=aria_controls
495+
usemap=usemap
496+
ismap=ismap
497+
elementtiming=elementtiming
498+
attributionsrc=attributionsrc
499+
/>
500+
</span>
501+
}
502+
.into_any(),
503+
504+
Layout::ScaleDown => view! {
505+
<span style="display:inline-block; position:relative; max-width:100%; max-height:100%;">
506+
<img
507+
node_ref=node_ref
508+
src=move || img_src.get()
509+
alt=alt
510+
class=class
511+
width=width
512+
height=height
513+
style=full_style.clone()
514+
sizes=sizes
515+
srcset=srcset
516+
decoding=decoding.as_str()
517+
crossorigin=crossorigin.as_str()
518+
referrerpolicy=referrerpolicy.as_str()
519+
loading=loading.as_str()
520+
fetchpriority=fetchpriority.as_str()
521+
aria_placeholder=placeholder
522+
on:load=onload
523+
on:error=onerror
524+
role="img"
525+
// aria-label=alt
526+
// aria-labelledby=aria_labelledby
527+
// aria-describedby=aria_describedby
528+
// aria-hidden=aria_hidden
529+
// aria-current=aria_current
530+
// aria-expanded=aria_expanded
531+
// aria-live=aria_live.as_str()
532+
// aria-pressed=aria_pressed.as_str()
533+
// aria-controls=aria_controls
534+
usemap=usemap
535+
ismap=ismap
536+
elementtiming=elementtiming
537+
attributionsrc=attributionsrc
538+
/>
539+
</span>
540+
}
541+
.into_any(),
332542
};
333543

334544
view! {

src/yew.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,6 @@ pub fn Image(props: &ImageProps) -> Html {
694694
aria-pressed={props.aria_pressed.as_str()}
695695
aria-controls={props.aria_controls}
696696
onerror={fetch_data}
697-
style={blur_style}
698697
crossorigin={props.crossorigin.as_str()}
699698
referrerpolicy={props.referrerpolicy.as_str()}
700699
fetchpriority={props.fetchpriority.as_str()}
@@ -737,7 +736,6 @@ pub fn Image(props: &ImageProps) -> Html {
737736
aria-pressed={props.aria_pressed.as_str()}
738737
aria-controls={props.aria_controls}
739738
onerror={fetch_data}
740-
style={blur_style}
741739
crossorigin={props.crossorigin.as_str()}
742740
referrerpolicy={props.referrerpolicy.as_str()}
743741
fetchpriority={props.fetchpriority.as_str()}

0 commit comments

Comments
 (0)