Adding in link, apply_methods, with_node, and on_click_go_to_url macros

This commit is contained in:
Pauan 2019-07-31 20:52:04 +02:00
parent b4aadeb42b
commit 2bed86b49e
5 changed files with 89 additions and 51 deletions

View File

@ -5,7 +5,7 @@ use wasm_bindgen::prelude::*;
use serde_derive::{Serialize, Deserialize};
use futures_signals::signal::{Signal, SignalExt, Mutable};
use futures_signals::signal_vec::{SignalVec, SignalVecExt, MutableVec};
use dominator::{Dom, text_signal, routing, html, clone, events};
use dominator::{Dom, text_signal, html, clone, events, link};
use crate::todo::Todo;
use crate::routing::Route;
@ -166,7 +166,7 @@ impl App {
fn render_button(text: &str, route: Route) -> Dom {
html!("li", {
.children(&mut [
routing::link(route.url(), |dom| { dom
link!(route.url(), {
.text(text)
.class_signal("selected", Route::signal().map(move |x| x == route))
})

View File

@ -2,10 +2,9 @@ use std::rc::Rc;
use wasm_bindgen::prelude::*;
use serde_derive::{Serialize, Deserialize};
use web_sys::HtmlElement;
use futures_signals::map_ref;
use futures_signals::signal::{SignalExt, Mutable};
use dominator::{Dom, html, clone, events};
use dominator::{Dom, html, clone, events, with_node};
use crate::util::trim;
use crate::app::App;
@ -120,20 +119,19 @@ impl Todo {
.focused_signal(todo.editing.signal_cloned()
.map(|x| x.is_some()))
.event(clone!(todo => move |event: events::KeyDown| {
match event.key().as_str() {
"Enter" => {
event.dyn_target::<HtmlElement>()
.unwrap_throw()
.blur()
.unwrap_throw();
},
"Escape" => {
todo.cancel_editing();
},
_ => {}
}
}))
.with_node!(element => {
.event(clone!(todo => move |event: events::KeyDown| {
match event.key().as_str() {
"Enter" => {
element.blur().unwrap_throw();
},
"Escape" => {
todo.cancel_editing();
},
_ => {}
}
}))
})
.event(clone!(todo => move |event: events::Input| {
todo.editing.set_neq(Some(event.value().unwrap_throw()));

View File

@ -380,6 +380,18 @@ pub struct DomBuilder<A> {
has_children: bool,
}
impl<A> DomBuilder<A> where A: JsCast {
#[inline]
pub fn new_html(name: &str) -> Self {
Self::new(create_element(name))
}
#[inline]
pub fn new_svg(name: &str) -> Self {
Self::new(create_element_ns(name, SVG_NAMESPACE))
}
}
impl<A> DomBuilder<A> {
#[inline]
pub fn new(value: A) -> Self {
@ -443,6 +455,7 @@ impl<A> DomBuilder<A> where A: Clone {
self.element.clone()
}
#[deprecated(since = "0.5.1", note = "Use the with_node macro instead")]
#[inline]
pub fn with_element<B, F>(self, f: F) -> B where F: FnOnce(Self, A) -> B {
let element = self.element.clone();

View File

@ -1,14 +1,16 @@
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_builder_method {
($this:expr,) => {
macro_rules! apply_methods {
($this:expr, {}) => {
$this
};
($this:expr, .$name:ident!($($args:tt)*) $($rest:tt)*) => {
$crate::__internal_builder_method!($name!($this, $($args)*), $($rest)*)
($this:expr, { .$name:ident!($($args:tt)*) $($rest:tt)* }) => {
$crate::apply_methods!({
let this = $this;
$name!(this, $($args)*)
}, { $($rest)* })
};
($this:expr, .$name:ident($($args:expr),*) $($rest:tt)*) => {
$crate::__internal_builder_method!($this.$name($($args),*), $($rest)*)
($this:expr, { .$name:ident($($args:expr),*) $($rest:tt)* }) => {
$crate::apply_methods!($this.$name($($args),*), { $($rest)* })
};
}
@ -16,32 +18,28 @@ macro_rules! __internal_builder_method {
#[doc(hidden)]
#[macro_export]
macro_rules! __internal_builder {
($default:ty, $name:ident => $make:expr, $kind:expr) => {
$crate::__internal_builder!($default, $name => $make, $kind => $default, {})
($default:ty, $make:ident, $kind:expr) => {
$crate::__internal_builder!($default, $make, $kind => $default, {})
};
($default:ty, $name:ident => $make:expr, $kind:expr, $($rest:tt)*) => {
$crate::__internal_builder!($default, $name => $make, $kind => $default, $($rest)*)
($default:ty, $make:ident, $kind:expr, $($rest:tt)*) => {
$crate::__internal_builder!($default, $make, $kind => $default, $($rest)*)
};
($default:ty, $name:ident => $make:expr, $kind:expr => $t:ty) => {
$crate::__internal_builder!($default, $name => $make, $kind => $t, {})
($default:ty, $make:ident, $kind:expr => $t:ty) => {
$crate::__internal_builder!($default, $make, $kind => $t, {})
};
($default:ty, $name:ident => $make:expr, $kind:expr => $t:ty, { $($methods:tt)* }) => {{
let a: $t = {
let $name = $kind;
$make
};
let b = $crate::DomBuilder::new(a);
let c = $crate::__internal_builder_method!(b, $($methods)*);
$crate::DomBuilder::into_dom(c)
($default:ty, $make:ident, $kind:expr => $t:ty, $($methods:tt)*) => {{
let builder = $crate::DomBuilder::<$t>::$make($kind);
let output = $crate::apply_methods!(builder, $($methods)*);
$crate::DomBuilder::into_dom(output)
}};
}
#[macro_export]
macro_rules! with_node {
($this:expr, $name:ident => { $($methods:tt)* }) => {{
($this:ident, $name:ident => { $($methods:tt)* }) => {{
let $name = $crate::DomBuilder::__internal_element(&$this);
$crate::__internal_builder_method!($this, $($methods)*)
$crate::apply_methods!($this, { $($methods)* })
}};
}
@ -49,7 +47,7 @@ macro_rules! with_node {
#[macro_export]
macro_rules! html {
($($args:tt)+) => {
$crate::__internal_builder!($crate::HtmlElement, kind => $crate::create_element(kind), $($args)+)
$crate::__internal_builder!($crate::HtmlElement, new_html, $($args)+)
};
}
@ -57,7 +55,7 @@ macro_rules! html {
#[macro_export]
macro_rules! svg {
($($args:tt)+) => {
$crate::__internal_builder!($crate::SvgElement, kind => $crate::create_element_ns(kind, $crate::SVG_NAMESPACE), $($args)+)
$crate::__internal_builder!($crate::SvgElement, new_svg, $($args)+)
};
}
@ -67,19 +65,17 @@ macro_rules! stylesheet {
($rule:expr) => {
$crate::stylesheet!($rule, {})
};
($rule:expr, { $($methods:tt)* }) => {{
let a = $crate::StylesheetBuilder::new($rule);
$crate::__internal_builder_method!(a, $($methods)*).done()
}};
($rule:expr, { $($methods:tt)* }) => {
$crate::apply_methods!($crate::StylesheetBuilder::new($rule), { $($methods)* }).done()
};
}
#[macro_export]
macro_rules! class {
($($methods:tt)*) => {{
let a = $crate::ClassBuilder::new();
$crate::__internal_builder_method!(a, $($methods)*).done()
}};
($($methods:tt)*) => {
$crate::apply_methods!($crate::ClassBuilder::new(), { $($methods)* }).done()
};
}

View File

@ -69,6 +69,7 @@ pub fn go_to_url(new_url: &str) {
}
#[deprecated(since = "0.5.1", note = "Use the on_click_go_to_url macro instead")]
#[inline]
pub fn on_click_go_to_url<A, B>(new_url: A) -> impl FnOnce(DomBuilder<B>) -> DomBuilder<B>
where A: Into<Cow<'static, str>>,
@ -87,6 +88,8 @@ pub fn on_click_go_to_url<A, B>(new_url: A) -> impl FnOnce(DomBuilder<B>) -> Dom
// TODO better type than HtmlElement
// TODO maybe make this a macro ?
#[deprecated(since = "0.5.1", note = "Use the link macro instead")]
#[allow(deprecated)]
#[inline]
pub fn link<A, F>(url: A, f: F) -> Dom
where A: Into<Cow<'static, str>>,
@ -99,3 +102,31 @@ pub fn link<A, F>(url: A, f: F) -> Dom
.apply(f)
})
}
// TODO test this
#[macro_export]
macro_rules! on_click_go_to_url {
($this:ident, $url:expr) => {{
let url = $url;
$this.event_preventable(move |e: $crate::events::Click| {
e.prevent_default();
$crate::routing::go_to_url(&url);
})
}};
}
// TODO test this
#[macro_export]
macro_rules! link {
($url:expr, { $($methods:tt)* }) => {{
let url = $url;
$crate::html!("a", {
.attribute("href", &url)
.apply(move |dom| $crate::on_click_go_to_url!(dom, url))
$($methods)*
})
}};
}