Virtual Elements
Position a floating element relative to a custom reference area, useful for context menus, range selections, following the cursor, and more.
Usage
A virtual element must implement the VirtualElement
trait.
pub trait VirtualElement<Element>: Clone + PartialEq {
fn get_bounding_client_rect(&self) -> ClientRectObject;
fn get_client_rects(&self) -> Option<Vec<ClientRectObject>>;
fn context_element(&self) -> Option<Element>;
}
A default implementation called DefaultVirtualElement
is provided for convience.
let virtual_el: Box<dyn VirtualElement<Element>> = Box::new(
DefaultVirtualElement::new(get_bounding_client_rect)
.get_client_rects(get_client_rects)
.context_element(context_element),
);
compute_position(virtual_el.into(), floating_el, ComputePositionConfig::new(platform))
get_bounding_client_rect
The most basic virtual element is a plain object that has a get_bounding_client_rect
method, which mimics a real element's one:
// A virtual element that is 20 x 20 px starting from (0, 0)
let virtual_el: Box<dyn VirtualElement<Element>> = Box::new(
DefaultVirtualElement::new(Rc::new(|| {
ClientRectObject {
x: 0.0,
y: 0.0,
top: 0.0,
left: 0.0,
bottom: 20.0,
right: 20.0,
width: 20.0,
height: 20.0,
}
}))
);
context_element
This option is useful if your get_bounding_client_rect
method is derived from a real element, to ensure clipping and position update detection works as expected.
let virtual_el: Box<dyn VirtualElement<Element>> = Box::new(
DefaultVirtualElement::new(get_bounding_client_rect)
.context_element(
web_sys::window()
.expext("Window should exist.")
.document()
.expect("Document should exist.")
.query_selector("#context")
.expect("Document should be queried.")
.expect("Element should exist."),
),
);
get_client_rects
This option is useful when using range selections and the Inline
middleware.
let virtual_el: Box<dyn VirtualElement<Element>> = Box::new(
DefaultVirtualElement::new(|| range.get_bounding_client_rect().into())
.get_client_rects(|| ClientRectObject::from_dom_rect_list(
range.get_client_rects().expect("Range should have client rects."),
)),
);