use std::cell::RefCell;
use std::rc::Rc;
use rdom_core::{ListenerOptions, NodeId};
use crate::TuiDom;
use crate::runtime::url_opener::{UrlOpener, is_external_scheme, scheme_of};
pub type SharedOpener = Rc<RefCell<Rc<dyn UrlOpener>>>;
pub fn install(dom: &mut TuiDom, opener: SharedOpener) {
let root = dom.root();
dom.add_event_listener(root, "click", ListenerOptions::default(), move |ctx| {
if ctx.event.default_prevented() {
return;
}
let Some(target) = ctx.event.target else {
return;
};
let Some(anchor) = anchor_with_href(ctx.dom, target) else {
return;
};
let href = ctx
.dom
.node(anchor)
.get_attribute("href")
.map(str::to_owned);
let Some(href) = href else {
return;
};
let scheme = scheme_of(&href);
if is_external_scheme(scheme) {
let opener_snapshot = opener.borrow().clone();
opener_snapshot.open(&href);
}
})
.expect("root click listener install");
}
fn anchor_with_href(dom: &TuiDom, id: NodeId) -> Option<NodeId> {
let mut cur = Some(id);
while let Some(n) = cur {
let node = dom.node(n);
if node.tag_name() == Some("a") && node.has_attribute("href") {
return Some(n);
}
cur = node.parent_node().map(|p| p.id());
}
None
}
#[cfg(test)]
mod tests;