diff --git a/src/dom.rs b/src/dom.rs index 0e7fe9c..f447174 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -504,49 +504,50 @@ impl DomBuilder { impl DomBuilder { #[inline] - pub fn style(self, name: &str, value: &str) -> Self { - dom_operations::set_style(&self.element, name, value, false); + pub fn style(self, name: B, value: &str) -> Self { + name.set_style(&self.element, value, false); self } #[inline] - pub fn style_important(self, name: &str, value: &str) -> Self { - dom_operations::set_style(&self.element, name, value, true); + pub fn style_important(self, name: B, value: &str) -> Self { + name.set_style(&self.element, value, true); self } } impl DomBuilder { - fn set_style_signal(&mut self, name: &str, value: C, important: bool) - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { - - let name = name.to_owned(); + fn set_style_signal(&mut self, name: B, value: D, important: bool) + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { set_option_str(&self.element, &mut self.callbacks, value, move |element, value| { match value { - Some(value) => dom_operations::set_style(element, &name, value, important), - None => dom_operations::remove_style(element, &name), + Some(value) => name.set_style(element, value, important), + None => name.remove_style(element), } }); } #[inline] - pub fn style_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.set_style_signal(name, value, false); self } #[inline] - pub fn style_important_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_important_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.set_style_signal(name, value, true); self @@ -627,48 +628,49 @@ impl StylesheetBuilder { } #[inline] - pub fn style(self, name: &str, value: &str) -> Self { - dom_operations::set_style(&self.element, name, value, false); + pub fn style(self, name: B, value: &str) -> Self { + name.set_style(&self.element, value, false); self } #[inline] - pub fn style_important(self, name: &str, value: &str) -> Self { - dom_operations::set_style(&self.element, name, value, true); + pub fn style_important(self, name: B, value: &str) -> Self { + name.set_style(&self.element, value, true); self } - fn set_style_signal(&mut self, name: &str, value: C, important: bool) - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { - - let name = name.to_owned(); + fn set_style_signal(&mut self, name: B, value: D, important: bool) + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { set_option_str(&self.element, &mut self.callbacks, value, move |element, value| { match value { - Some(value) => dom_operations::set_style(element, &name, value, important), - None => dom_operations::remove_style(element, &name), + Some(value) => name.set_style(element, value, important), + None => name.remove_style(element), } }); } #[inline] - pub fn style_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.set_style_signal(name, value, false); self } #[inline] - pub fn style_important_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_important_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.set_style_signal(name, value, true); self @@ -720,32 +722,34 @@ impl ClassBuilder { } #[inline] - pub fn style(mut self, name: &str, value: &str) -> Self { + pub fn style(mut self, name: B, value: &str) -> Self { self.stylesheet = self.stylesheet.style(name, value); self } #[inline] - pub fn style_important(mut self, name: &str, value: &str) -> Self { + pub fn style_important(mut self, name: B, value: &str) -> Self { self.stylesheet = self.stylesheet.style_important(name, value); self } #[inline] - pub fn style_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.stylesheet = self.stylesheet.style_signal(name, value); self } #[inline] - pub fn style_important_signal(mut self, name: &str, value: C) -> Self - where B: IntoOptionStr, - C: IntoSignal, - C::Signal: 'static { + pub fn style_important_signal(mut self, name: B, value: D) -> Self + where B: StyleName + 'static, + C: IntoOptionStr, + D: IntoSignal, + D::Signal: 'static { self.stylesheet = self.stylesheet.style_important_signal(name, value); self @@ -799,35 +803,18 @@ mod tests { .style_signal("foo", always("bar")) .style_signal("foo", always("bar".to_owned())) .style_signal("foo", always("bar".to_owned()).map(|x| DerefFn::new(x, |x| x.as_str()))) - //.style_signal("foo", always(Arc::new("bar"))) - //.style_signal("foo", always(Arc::new("bar".to_owned()))) - //.style_signal("foo", always(Rc::new("bar"))) - //.style_signal("foo", always(Rc::new("bar".to_owned()))) - //.style_signal("foo", always(Box::new("bar"))) - //.style_signal("foo", always(Box::new("bar".to_owned()))) - //.style_signal("foo", always(Cow::Borrowed(&"bar"))) - //.style_signal("foo", always(Cow::Owned::("bar".to_owned()))) + + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar")) + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned())) + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned()).map(|x| DerefFn::new(x, |x| x.as_str()))) .style_signal("foo", always(Some("bar"))) .style_signal("foo", always(Some("bar".to_owned()))) .style_signal("foo", always("bar".to_owned()).map(|x| Some(DerefFn::new(x, |x| x.as_str())))) - //.style_signal("foo", always(Some(Arc::new("bar")))) - //.style_signal("foo", always(Some(Arc::new("bar".to_owned())))) - //.style_signal("foo", always(Some(Rc::new("bar")))) - //.style_signal("foo", always(Some(Rc::new("bar".to_owned())))) - //.style_signal("foo", always(Some(Box::new("bar")))) - //.style_signal("foo", always(Some(Box::new("bar".to_owned())))) - //.style_signal("foo", always(Some(Cow::Borrowed(&"bar")))) - //.style_signal("foo", always(Some(Cow::Owned::("bar".to_owned())))) - /*.style_signal("foo", always(Arc::new(Some("bar")))) - .style_signal("foo", always(Arc::new(Some("bar".to_owned())))) - .style_signal("foo", always(Rc::new(Some("bar")))) - .style_signal("foo", always(Rc::new(Some("bar".to_owned())))) - .style_signal("foo", always(Box::new(Some("bar")))) - .style_signal("foo", always(Box::new(Some("bar".to_owned())))) - .style_signal("foo", always(Cow::Borrowed(&Some("bar")))) - .style_signal("foo", always(Cow::Owned::>(Some("bar".to_owned()))))*/ + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(Some("bar"))) + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always(Some("bar".to_owned()))) + .style_signal(["-moz-foo", "-webkit-foo", "foo"], always("bar".to_owned()).map(|x| Some(DerefFn::new(x, |x| x.as_str())))) ; } diff --git a/src/dom_operations.rs b/src/dom_operations.rs index 0632587..5aa69c5 100644 --- a/src/dom_operations.rs +++ b/src/dom_operations.rs @@ -59,6 +59,11 @@ pub fn set_text(element: &TextNode, value: &str) { } +#[inline] +fn get_style>(element: &A, name: &str) -> String { + js!( return @{element.as_ref()}.style.getPropertyValue(@{name}); ).try_into().unwrap() +} + #[inline] fn set_style_raw>(element: &A, name: &str, value: &str, important: bool) { js! { @(no_return) @@ -67,28 +72,14 @@ fn set_style_raw>(element: &A, name: &str, value: &str, impo } // TODO this should be in stdweb -// TODO handle browser prefixes -#[cfg(debug_assertions)] -pub fn set_style>(element: &A, name: &str, value: &str, important: bool) { +// TODO maybe use cfg(debug_assertions) ? +pub fn try_set_style>(element: &A, name: &str, value: &str, important: bool) -> bool { assert!(value != ""); - #[inline] - fn get_style>(element: &A, name: &str) -> String { - js!( return @{element.as_ref()}.style.getPropertyValue(@{name}); ).try_into().unwrap() - } - remove_style(element, name); set_style_raw(element, name, value, important); - if get_style(element, name) == "" { - panic!("style is incorrect:\n name: {}\n value: {}", name, value); - } -} - -#[cfg(not(debug_assertions))] -#[inline] -pub fn set_style>(element: &A, name: &str, value: &str, important: bool) { - set_style_raw(element, name, value, important); + get_style(element, name) != "" } // TODO this should be in stdweb diff --git a/src/traits.rs b/src/traits.rs index e79bcbf..a826af5 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,5 +1,7 @@ +use dom_operations; use dom::DerefFn; use std::ops::Deref; +use stdweb::Reference; pub use animation::AnimatedSignalVec; @@ -16,6 +18,63 @@ impl Mixin for F where F: Fn(A) -> A { } +pub trait StyleName { + fn set_style>(&self, element: &A, value: &str, important: bool); + fn remove_style>(&self, element: &A); +} + +impl<'a> StyleName for &'a str { + #[inline] + fn set_style>(&self, element: &A, value: &str, important: bool) { + if !dom_operations::try_set_style(element, self, value, important) { + panic!("style is incorrect:\n name: {}\n value: {}", self, value); + } + } + + #[inline] + fn remove_style>(&self, element: &A) { + dom_operations::remove_style(element, self); + } +} + + +macro_rules! array_style_name { + ($size:expr) => { + impl<'a> StyleName for [&'a str; $size] { + #[inline] + fn set_style>(&self, element: &A, value: &str, important: bool) { + let mut okay = false; + + for name in self.iter() { + if dom_operations::try_set_style(element, name, value, important) { + okay = true; + } + } + + if !okay { + panic!("style is incorrect:\n names: {}\n value: {}", self.join(", "), value); + } + } + + #[inline] + fn remove_style>(&self, element: &A) { + for name in self.iter() { + dom_operations::remove_style(element, name); + } + } + } + }; +} + +macro_rules! array_style_names { + ($($size:expr),*) => { + $(array_style_name!($size);)* + }; +} + +array_style_names!(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + + // TODO figure out a way to implement this for all of AsRef / Borrow / etc. // TODO implementations for &String and &mut String pub trait IntoStr {