Adding in DomChildren implementation for Signal
This commit is contained in:
parent
874832e82b
commit
e7e22f3b21
|
@ -1,4 +1,4 @@
|
|||
|
||||
/target
|
||||
target/
|
||||
**/*.rs.bk
|
||||
Cargo.lock
|
||||
|
|
|
@ -26,35 +26,54 @@ fn main() {
|
|||
style("border-left", "10px solid teal");
|
||||
});*/
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
let (sender_elements, receiver_elements) = signal::unsync::mutable(count);
|
||||
|
||||
|
||||
let mut width = 100;
|
||||
|
||||
let (sender, receiver) = signal::unsync::mutable(width);
|
||||
|
||||
|
||||
html!("div", {
|
||||
style("border", "10px solid blue");
|
||||
children(&mut [
|
||||
children([
|
||||
html!("div", {
|
||||
style("width", receiver.map(|x| Some(format!("{}px", x))));
|
||||
style("height", "50px");
|
||||
style("background-color", "green");
|
||||
event(move |event: ClickEvent| {
|
||||
count += 1;
|
||||
width += 100;
|
||||
|
||||
console!(log, &event);
|
||||
|
||||
sender.set(width).unwrap();
|
||||
sender_elements.set(count).unwrap();
|
||||
});
|
||||
children(receiver_elements.map(|count| {
|
||||
(0..count).map(|_| {
|
||||
html!("div", {
|
||||
style("border", "5px solid red");
|
||||
style("width", "50px");
|
||||
style("height", "50px");
|
||||
})
|
||||
})
|
||||
}));
|
||||
}),
|
||||
|
||||
html!("div", {
|
||||
style("width", "50px");
|
||||
style("height", "50px");
|
||||
style("background-color", "red");
|
||||
children(&mut [
|
||||
children([
|
||||
html!("div", {
|
||||
style("width", "10px");
|
||||
style("height", "10px");
|
||||
style("background-color", "orange");
|
||||
})
|
||||
]);
|
||||
].as_mut());
|
||||
}),
|
||||
|
||||
html!("div", {
|
||||
|
@ -62,13 +81,13 @@ fn main() {
|
|||
style("height", "50px");
|
||||
style("background-color", "red");
|
||||
class(&foobar, true);
|
||||
children(&mut [
|
||||
children([
|
||||
html!("div", {
|
||||
style("width", "10px");
|
||||
style("height", "10px");
|
||||
style("background-color", "orange");
|
||||
})
|
||||
]);
|
||||
].as_mut());
|
||||
}),
|
||||
|
||||
Dom::with_state(Rc::new(vec![1, 2, 3]), |a| {
|
||||
|
@ -87,7 +106,7 @@ fn main() {
|
|||
html!("input", {
|
||||
focused(true);
|
||||
}),
|
||||
]);
|
||||
].as_mut());
|
||||
}).insert_into(
|
||||
&document().query_selector("body").unwrap().unwrap()
|
||||
);
|
||||
|
|
53
src/dom.rs
53
src/dom.rs
|
@ -102,7 +102,7 @@ pub mod dom_operations {
|
|||
use std;
|
||||
use stdweb::unstable::{TryFrom, TryInto};
|
||||
use stdweb::{Value, Reference};
|
||||
use stdweb::web::{TextNode, IHtmlElement, IElement};
|
||||
use stdweb::web::{TextNode, INode, IHtmlElement, IElement};
|
||||
|
||||
|
||||
#[inline]
|
||||
|
@ -198,6 +198,16 @@ pub mod dom_operations {
|
|||
@{obj.as_ref()}[@{name}] = @{value};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO make this work on Nodes, not just Elements
|
||||
// TODO is this the most efficient way to remove all children ?
|
||||
#[inline]
|
||||
pub fn remove_all_children<A: INode>(element: &A) {
|
||||
js! { @(no_return)
|
||||
@{element.as_ref()}.innerHTML = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -235,7 +245,20 @@ pub mod internal {
|
|||
|
||||
pub struct RemoveCallback(Box<IRemoveCallback>);
|
||||
|
||||
impl std::fmt::Debug for InsertCallback {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "InsertCallback")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RemoveCallback {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "RemoveCallback")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Callbacks {
|
||||
pub after_insert: Vec<InsertCallback>,
|
||||
pub after_remove: Vec<RemoveCallback>,
|
||||
|
@ -336,6 +359,7 @@ impl DomBuilder for TextBuilder {
|
|||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Dom {
|
||||
element: Node,
|
||||
callbacks: Callbacks,
|
||||
|
@ -586,7 +610,8 @@ impl DomFocused for bool {
|
|||
}
|
||||
|
||||
// TODO figure out how to make this owned rather than &mut
|
||||
impl<'a, A: IntoIterator<Item = &'a mut Dom>> DomChildren for A {
|
||||
// TODO impl<'a, A: IntoIterator<Item = &'a mut Dom>> DomChildren for A {
|
||||
impl<'a> DomChildren for &'a mut [Dom] {
|
||||
#[inline]
|
||||
fn insert_children<B: INode, C: DomBuilder<Value = B>>(self, builder: &mut C) {
|
||||
for dom in self.into_iter() {
|
||||
|
@ -686,6 +711,30 @@ impl<S: Signal<Value = bool> + 'static> DomFocused for S {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: IntoIterator<Item = Dom>, S: Signal<Value = A> + 'static> DomChildren for S {
|
||||
// TODO inline this ?
|
||||
fn insert_children<B: INode + Clone + 'static, C: DomBuilder<Value = B>>(self, builder: &mut C) {
|
||||
let element = builder.value().clone();
|
||||
|
||||
let mut old_children: Vec<Dom> = vec![];
|
||||
|
||||
let handle = self.for_each(move |value| {
|
||||
dom_operations::remove_all_children(&element);
|
||||
|
||||
old_children = value.into_iter().map(|mut dom| {
|
||||
element.append_child(&dom.element);
|
||||
|
||||
// TODO don't trigger this if the parent isn't inserted into the DOM
|
||||
dom.callbacks.trigger_after_insert();
|
||||
|
||||
dom
|
||||
}).collect();
|
||||
});
|
||||
|
||||
builder.callbacks().after_remove(move || handle.stop());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct StylesheetBuilder {
|
||||
element: CssStyleRule,
|
||||
|
|
|
@ -70,9 +70,10 @@ pub trait Signal {
|
|||
self.map(callback).flatten()
|
||||
}
|
||||
|
||||
// TODO file Rust bug about bad error message when `callback` isn't marked as `mut`
|
||||
// TODO make this more efficient
|
||||
fn for_each<A>(self, callback: A) -> DropHandle
|
||||
where A: Fn(Self::Value) + 'static,
|
||||
fn for_each<A>(self, mut callback: A) -> DropHandle
|
||||
where A: FnMut(Self::Value) + 'static,
|
||||
Self: Sized + 'static {
|
||||
|
||||
let (handle, stream) = drop_handle(self.to_stream());
|
||||
|
|
Loading…
Reference in New Issue