mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 14:54:16 +00:00
Add some often-used helper functions
This commit is contained in:
parent
aa10ab861a
commit
432eda8d6d
1 changed files with 129 additions and 0 deletions
129
leptos_dom/src/helpers.rs
Normal file
129
leptos_dom/src/helpers.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
use crate::{window, document, is_server};
|
||||
use std::time::Duration;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use wasm_bindgen::convert::FromWasmAbi;
|
||||
use wasm_bindgen::{prelude::Closure, JsCast, JsValue, UnwrapThrowExt};
|
||||
|
||||
/// Sets a property on a DOM element.
|
||||
pub fn set_property(el: &web_sys::Element, prop_name: &str, value: &Option<JsValue>) {
|
||||
let key = JsValue::from_str(prop_name);
|
||||
match value {
|
||||
Some(value) => _ = js_sys::Reflect::set(el, &key, value),
|
||||
None => _ = js_sys::Reflect::delete_property(el, &key),
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the current [`window.location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location).
|
||||
pub fn location() -> web_sys::Location {
|
||||
window().location()
|
||||
}
|
||||
|
||||
/// Current [`window.location.hash`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location)
|
||||
/// without the beginning #.
|
||||
pub fn location_hash() -> Option<String> {
|
||||
if is_server!() {
|
||||
None
|
||||
} else {
|
||||
location().hash().ok().map(|hash| hash.replace('#', ""))
|
||||
}
|
||||
}
|
||||
|
||||
/// Current [`window.location.pathname`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location).
|
||||
pub fn location_pathname() -> Option<String> {
|
||||
location().pathname().ok()
|
||||
}
|
||||
|
||||
/// Helper function to extract [`Event.target`](https://developer.mozilla.org/en-US/docs/Web/API/Event/target)
|
||||
/// from any event.
|
||||
pub fn event_target<T>(event: &web_sys::Event) -> T
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
event.target().unwrap_throw().unchecked_into::<T>()
|
||||
}
|
||||
|
||||
/// Helper function to extract `event.target.value` from an event.
|
||||
///
|
||||
/// This is useful in the `on:input` or `on:change` listeners for an `<input>` element.
|
||||
pub fn event_target_value<T>(event: &T) -> String
|
||||
where
|
||||
T: JsCast,
|
||||
{
|
||||
event
|
||||
.unchecked_ref::<web_sys::Event>()
|
||||
.target()
|
||||
.unwrap_throw()
|
||||
.unchecked_into::<web_sys::HtmlInputElement>()
|
||||
.value()
|
||||
}
|
||||
|
||||
/// Helper function to extract `event.target.checked` from an event.
|
||||
///
|
||||
/// This is useful in the `on:change` listeners for an `<input type="checkbox">` element.
|
||||
pub fn event_target_checked(ev: &web_sys::Event) -> bool {
|
||||
ev.target()
|
||||
.unwrap()
|
||||
.unchecked_into::<web_sys::HtmlInputElement>()
|
||||
.checked()
|
||||
}
|
||||
|
||||
/// Runs the given function between the next repaint
|
||||
/// using [`Window.requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame).
|
||||
pub fn request_animation_frame(cb: impl FnMut() + 'static) {
|
||||
let cb = Closure::wrap(Box::new(cb) as Box<dyn FnMut()>).into_js_value();
|
||||
_ = window().request_animation_frame(cb.as_ref().unchecked_ref());
|
||||
}
|
||||
|
||||
/// Queues the given function during an idle period
|
||||
/// using [`Window.requestIdleCallback`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestIdleCallback).
|
||||
pub fn request_idle_callback(cb: impl Fn() + 'static) {
|
||||
let cb = Closure::wrap(Box::new(cb) as Box<dyn Fn()>).into_js_value();
|
||||
_ = window().request_idle_callback(cb.as_ref().unchecked_ref());
|
||||
}
|
||||
|
||||
/// Executes the given function after the given duration of time has passed.
|
||||
/// [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout).
|
||||
pub fn set_timeout(cb: impl FnOnce() + 'static, duration: Duration) {
|
||||
let cb = Closure::once_into_js(Box::new(cb) as Box<dyn FnOnce()>);
|
||||
_ = window().set_timeout_with_callback_and_timeout_and_arguments_0(
|
||||
cb.as_ref().unchecked_ref(),
|
||||
duration.as_millis().try_into().unwrap_throw(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Handle that is generated by [set_interval] and can be used to clear the interval.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct IntervalHandle(i32);
|
||||
|
||||
impl IntervalHandle {
|
||||
/// Cancels the repeating event to which this refers.
|
||||
/// See [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)
|
||||
pub fn clear(&self) {
|
||||
window().clear_interval_with_handle(self.0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Repeatedly calls the given function, with a delay of the given duration between calls.
|
||||
/// See [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval).
|
||||
pub fn set_interval(
|
||||
cb: impl Fn() + 'static,
|
||||
duration: Duration,
|
||||
) -> Result<IntervalHandle, JsValue> {
|
||||
let cb = Closure::wrap(Box::new(cb) as Box<dyn Fn()>).into_js_value();
|
||||
let handle = window().set_interval_with_callback_and_timeout_and_arguments_0(
|
||||
cb.as_ref().unchecked_ref(),
|
||||
duration.as_millis().try_into().unwrap_throw(),
|
||||
)?;
|
||||
Ok(IntervalHandle(handle))
|
||||
}
|
||||
|
||||
/// Adds an event listener to the `Window`.
|
||||
pub fn window_event_listener(event_name: &str, cb: impl Fn(web_sys::Event) + 'static) {
|
||||
if !is_server!() {
|
||||
let handler = Box::new(cb) as Box<dyn FnMut(web_sys::Event)>;
|
||||
|
||||
let cb = Closure::wrap(handler).into_js_value();
|
||||
_ = window().add_event_listener_with_callback(event_name, cb.unchecked_ref());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue