Adding in DomChildren implementation for Signal

This commit is contained in:
Pauan 2018-02-20 22:08:36 -10:00
parent 874832e82b
commit e7e22f3b21
4 changed files with 80 additions and 11 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
/target
target/
**/*.rs.bk
Cargo.lock

View File

@ -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()
);

View File

@ -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,

View File

@ -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());