It now supports multiple dynamic children, by using comment markers
This commit is contained in:
parent
16f09dd375
commit
2839a51ba9
|
@ -124,6 +124,12 @@ pub(crate) fn create_comment(value: &str) -> Comment {
|
|||
DOCUMENT.with(|d| d.create_comment(value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn create_empty_node() -> Node {
|
||||
// TODO is there a better way of doing this ?
|
||||
create_comment(intern("")).into()
|
||||
}
|
||||
|
||||
// TODO check that the attribute *actually* was changed
|
||||
pub(crate) fn set_attribute(elem: &Element, key: &str, value: &str) {
|
||||
elem.set_attribute(key, value).unwrap_throw();
|
||||
|
|
19
src/dom.rs
19
src/dom.rs
|
@ -245,8 +245,7 @@ impl Dom {
|
|||
|
||||
#[inline]
|
||||
pub fn empty() -> Self {
|
||||
// TODO is there a better way of doing this ?
|
||||
Self::new(bindings::create_comment(intern("")).into())
|
||||
Self::new(bindings::create_empty_node())
|
||||
}
|
||||
|
||||
#[deprecated(since = "0.5.15", note = "Store the data explicitly in a component struct instead")]
|
||||
|
@ -386,8 +385,6 @@ fn set_property<A, B, C>(element: &A, name: &B, value: C) where A: AsRef<JsValue
|
|||
pub struct DomBuilder<A> {
|
||||
element: A,
|
||||
callbacks: Callbacks,
|
||||
// TODO verify this with static types instead ?
|
||||
dynamic_children: bool,
|
||||
}
|
||||
|
||||
impl<A> DomBuilder<A> where A: JsCast {
|
||||
|
@ -416,7 +413,6 @@ impl<A> DomBuilder<A> {
|
|||
Self {
|
||||
element: value,
|
||||
callbacks: Callbacks::new(),
|
||||
dynamic_children: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,14 +573,8 @@ impl<A> DomBuilder<A> where A: AsRef<EventTarget> {
|
|||
}
|
||||
|
||||
impl<A> DomBuilder<A> where A: AsRef<Node> {
|
||||
#[inline]
|
||||
fn check_children(&self) {
|
||||
assert_eq!(self.dynamic_children, false);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn child<B: BorrowMut<Dom>>(mut self, mut child: B) -> Self {
|
||||
self.check_children();
|
||||
operations::insert_children_one(self.element.as_ref(), &mut self.callbacks, child.borrow_mut());
|
||||
self
|
||||
}
|
||||
|
@ -592,14 +582,12 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
|
|||
// TODO figure out how to make this owned rather than &mut
|
||||
#[inline]
|
||||
pub fn children<B: BorrowMut<Dom>, C: IntoIterator<Item = B>>(mut self, children: C) -> Self {
|
||||
self.check_children();
|
||||
operations::insert_children_iter(self.element.as_ref(), &mut self.callbacks, children);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn text(self, value: &str) -> Self {
|
||||
self.check_children();
|
||||
// TODO should this intern ?
|
||||
bindings::append_child(self.element.as_ref(), &bindings::create_text_node(value));
|
||||
self
|
||||
|
@ -610,7 +598,6 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
|
|||
where B: AsStr,
|
||||
C: Signal<Item = B> + 'static {
|
||||
|
||||
self.check_children();
|
||||
let element = make_text_signal(&mut self.callbacks, value);
|
||||
bindings::append_child(self.element.as_ref(), &element);
|
||||
self
|
||||
|
@ -620,8 +607,6 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
|
|||
pub fn children_signal_vec<B>(mut self, children: B) -> Self
|
||||
where B: SignalVec<Item = Dom> + 'static {
|
||||
|
||||
self.check_children();
|
||||
self.dynamic_children = true;
|
||||
operations::insert_children_signal_vec(self.element.as_ref().clone(), &mut self.callbacks, children);
|
||||
self
|
||||
}
|
||||
|
@ -630,8 +615,6 @@ impl<A> DomBuilder<A> where A: AsRef<Node> {
|
|||
pub fn child_signal<B>(mut self, child: B) -> Self
|
||||
where B: Signal<Item = Option<Dom>> + 'static {
|
||||
|
||||
self.check_children();
|
||||
self.dynamic_children = true;
|
||||
operations::insert_child_signal(self.element.as_ref().clone(), &mut self.callbacks, child);
|
||||
self
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ pub(crate) fn insert_child_signal<A>(element: Node, callbacks: &mut Callbacks, s
|
|||
}
|
||||
|
||||
// TODO verify that this will drop `child`
|
||||
fn after_remove(&mut self, element: &Node, child: Option<Dom>) {
|
||||
fn after_remove(&mut self, element: &Node, marker: &Node, child: Option<Dom>) {
|
||||
if let Some(old_child) = self.child.take() {
|
||||
bindings::remove_child(&element, &old_child.element);
|
||||
|
||||
|
@ -121,7 +121,7 @@ pub(crate) fn insert_child_signal<A>(element: Node, callbacks: &mut Callbacks, s
|
|||
self.child = child;
|
||||
|
||||
if let Some(new_child) = &mut self.child {
|
||||
bindings::append_child(&element, &new_child.element);
|
||||
bindings::insert_child_before(element, &new_child.element, marker);
|
||||
|
||||
after_insert(self.is_inserted, &mut new_child.callbacks);
|
||||
}
|
||||
|
@ -147,6 +147,11 @@ pub(crate) fn insert_child_signal<A>(element: Node, callbacks: &mut Callbacks, s
|
|||
}
|
||||
}
|
||||
|
||||
// TODO replace with https://github.com/whatwg/dom/issues/736
|
||||
let marker = bindings::create_empty_node();
|
||||
|
||||
bindings::append_child(&element, &marker);
|
||||
|
||||
let state = State::new();
|
||||
|
||||
State::after_insert(state.clone(), callbacks);
|
||||
|
@ -155,7 +160,7 @@ pub(crate) fn insert_child_signal<A>(element: Node, callbacks: &mut Callbacks, s
|
|||
state: state.clone(),
|
||||
signal: for_each(signal, move |child| {
|
||||
let mut state = state.borrow_mut();
|
||||
state.after_remove(&element, child);
|
||||
state.after_remove(&element, &marker, child);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
@ -167,14 +172,16 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
|
||||
struct State {
|
||||
element: Node,
|
||||
marker: Node,
|
||||
is_inserted: bool,
|
||||
children: Vec<Dom>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
fn new(element: Node) -> Rc<RefCell<Self>> {
|
||||
fn new(element: Node, marker: Node) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(State {
|
||||
element,
|
||||
marker,
|
||||
is_inserted: false,
|
||||
children: vec![],
|
||||
}))
|
||||
|
@ -212,7 +219,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
bindings::insert_child_before(&self.element, child, &dom.element);
|
||||
|
||||
} else {
|
||||
bindings::append_child(&self.element, child);
|
||||
bindings::insert_child_before(&self.element, child, &self.marker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,8 +233,9 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
|
||||
let is_inserted = self.is_inserted;
|
||||
|
||||
// TODO use createDocumentFragment ?
|
||||
for dom in self.children.iter_mut() {
|
||||
bindings::append_child(&self.element, &dom.element);
|
||||
bindings::insert_child_before(&self.element, &dom.element, &self.marker);
|
||||
|
||||
after_insert(is_inserted, &mut dom.callbacks);
|
||||
}
|
||||
|
@ -243,7 +251,7 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
},
|
||||
|
||||
VecDiff::Push { mut value } => {
|
||||
bindings::append_child(&self.element, &value.element);
|
||||
bindings::insert_child_before(&self.element, &value.element, &self.marker);
|
||||
|
||||
after_insert(self.is_inserted, &mut value.callbacks);
|
||||
|
||||
|
@ -309,7 +317,12 @@ pub(crate) fn insert_children_signal_vec<A>(element: Node, callbacks: &mut Callb
|
|||
}
|
||||
}
|
||||
|
||||
let state = State::new(element);
|
||||
// TODO replace with https://github.com/whatwg/dom/issues/736
|
||||
let marker = bindings::create_empty_node();
|
||||
|
||||
bindings::append_child(&element, &marker);
|
||||
|
||||
let state = State::new(element, marker);
|
||||
|
||||
State::after_insert(state.clone(), callbacks);
|
||||
|
||||
|
|
Loading…
Reference in New Issue