diff --git a/pagetop-homedemo/src/lib.rs b/pagetop-homedemo/src/lib.rs index 9dc8fe2a..5c8f4a07 100644 --- a/pagetop-homedemo/src/lib.rs +++ b/pagetop-homedemo/src/lib.rs @@ -38,7 +38,7 @@ async fn demo(request: service::HttpRequest) -> ResultPage { .with_context(ContextOp::AddStyleSheet(StyleSheet::at( "/homedemo/css/styles.css", ))) - .with_body_classes(ClassesOp::AddFirst, "default-homepage") + .with_body_classes(ClassesOp::Add, "default-homepage") .with_in("content", hello_world()) .with_in("content", welcome()) .with_in("content", about_pagetop()) diff --git a/pagetop-minimal/src/component/form_element/button.rs b/pagetop-minimal/src/component/form_element/button.rs index 85b9b504..af7e09a7 100644 --- a/pagetop-minimal/src/component/form_element/button.rs +++ b/pagetop-minimal/src/component/form_element/button.rs @@ -30,7 +30,7 @@ impl ComponentTrait for Button { fn new() -> Self { Button::default() .with_classes(ClassesOp::SetDefault, "btn btn-primary") - .with_classes(ClassesOp::AddFirst, "form-button") + .with_classes(ClassesOp::Add, "form-button") } fn handle(&self) -> Handle { @@ -76,7 +76,7 @@ impl Button { pub fn submit(value: L10n) -> Self { let mut button = Button::new() - .with_classes(ClassesOp::Replace("form-button"), "form-submit") + .with_classes(ClassesOp::Replace("form-button".to_owned()), "form-submit") .with_value(value); button.button_type = ButtonType::Submit; button @@ -84,7 +84,7 @@ impl Button { pub fn reset(value: L10n) -> Self { let mut button = Button::new() - .with_classes(ClassesOp::Replace("form-button"), "form-reset") + .with_classes(ClassesOp::Replace("form-button".to_owned()), "form-reset") .with_value(value); button.button_type = ButtonType::Reset; button diff --git a/pagetop-minimal/src/component/form_element/date.rs b/pagetop-minimal/src/component/form_element/date.rs index 9b4748fd..c14979f9 100644 --- a/pagetop-minimal/src/component/form_element/date.rs +++ b/pagetop-minimal/src/component/form_element/date.rs @@ -25,7 +25,7 @@ impl ComponentTrait for Date { fn new() -> Self { Date::default() .with_classes(ClassesOp::SetDefault, "form-item") - .with_classes(ClassesOp::AddFirst, "form-type-date") + .with_classes(ClassesOp::Add, "form-type-date") } fn handle(&self) -> Handle { diff --git a/pagetop-minimal/src/component/form_element/input.rs b/pagetop-minimal/src/component/form_element/input.rs index dd2a97c5..740c8a2c 100644 --- a/pagetop-minimal/src/component/form_element/input.rs +++ b/pagetop-minimal/src/component/form_element/input.rs @@ -43,7 +43,7 @@ impl ComponentTrait for Input { fn new() -> Self { Input::default() .with_classes(ClassesOp::SetDefault, "form-item") - .with_classes(ClassesOp::AddFirst, "form-type-textfield") + .with_classes(ClassesOp::Add, "form-type-textfield") .with_size(Some(60)) .with_maxlength(Some(128)) } @@ -113,51 +113,46 @@ impl Input { Input::new() } - #[rustfmt::skip] pub fn password() -> Self { let mut input = Input::new().with_classes( - ClassesOp::Replace("form-type-textfield"), + ClassesOp::Replace("form-type-textfield".to_owned()), "form-type-password", ); input.input_type = InputType::Password; input } - #[rustfmt::skip] pub fn search() -> Self { let mut input = Input::new().with_classes( - ClassesOp::Replace("form-type-textfield"), + ClassesOp::Replace("form-type-textfield".to_owned()), "form-type-search", ); input.input_type = InputType::Search; input } - #[rustfmt::skip] pub fn email() -> Self { let mut input = Input::new().with_classes( - ClassesOp::Replace("form-type-textfield"), - "form-type-email" + ClassesOp::Replace("form-type-textfield".to_owned()), + "form-type-email", ); input.input_type = InputType::Email; input } - #[rustfmt::skip] pub fn telephone() -> Self { let mut input = Input::new().with_classes( - ClassesOp::Replace("form-type-textfield"), + ClassesOp::Replace("form-type-textfield".to_owned()), "form-type-telephone", ); input.input_type = InputType::Telephone; input } - #[rustfmt::skip] pub fn url() -> Self { let mut input = Input::new().with_classes( - ClassesOp::Replace("form-type-textfield"), - "form-type-url" + ClassesOp::Replace("form-type-textfield".to_owned()), + "form-type-url", ); input.input_type = InputType::Url; input diff --git a/pagetop/src/html/classes.rs b/pagetop/src/html/classes.rs index f9f4ee04..2ebc457c 100644 --- a/pagetop/src/html/classes.rs +++ b/pagetop/src/html/classes.rs @@ -1,24 +1,22 @@ -use crate::{concat_string, fn_builder}; +use crate::fn_builder; pub enum ClassesOp { Add, - AddAfter(&'static str), - AddBefore(&'static str), - AddFirst, Remove, - Replace(&'static str), + Replace(String), Reset, SetDefault, - SetDefaultIfEmpty, } -#[rustfmt::skip] -#[derive(Default)] -pub struct Classes { - default: String, - added : String, +#[derive(Eq, PartialEq)] +enum ClassType { + Default, + User, } +#[derive(Default)] +pub struct Classes(Vec<(String, ClassType)>); + impl Classes { pub fn new() -> Self { Classes::default() @@ -28,64 +26,49 @@ impl Classes { #[fn_builder] pub fn alter_value(&mut self, op: ClassesOp, classes: &str) -> &mut Self { - let classes = classes.trim(); + let classes: Vec = classes + .split_ascii_whitespace() + .map(|c| c.to_owned()) + .collect(); + match op { ClassesOp::Add => { - self.added = concat_string!(self.added, " ", classes).trim().to_owned() - } - - ClassesOp::AddAfter(class) => { - let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); - match v_added.iter().position(|c| c.eq(&class)) { - Some(pos) => v_added.insert(pos + 1, classes), - _ => v_added.push(classes), + for class in classes { + if self.0.iter().position(|(c, _)| c.eq(&class)).is_none() { + self.0.push((class, ClassType::User)); + } } - self.added = v_added.join(" "); - } - - ClassesOp::AddBefore(class) => { - let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); - match v_added.iter().position(|c| c.eq(&class)) { - Some(pos) => v_added.insert(pos, classes), - _ => v_added.insert(0, classes), - } - self.added = v_added.join(" "); - } - - ClassesOp::AddFirst => { - self.added = concat_string!(classes, " ", self.added).trim().to_owned() } ClassesOp::Remove => { - let v_list: Vec<&str> = classes.split_ascii_whitespace().collect(); - let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); - for class in v_list { - if let Some(pos) = v_added.iter().position(|c| c.eq(&class)) { - v_added.remove(pos); - } + for class in classes { + self.0 + .retain(|(c, t)| c.ne(&class) || t.ne(&ClassType::User)); } - self.added = v_added.join(" "); } - ClassesOp::Replace(class) => { - let mut v_added: Vec<&str> = self.added.split_ascii_whitespace().collect(); - match v_added.iter().position(|c| c.eq(&class)) { - Some(pos) => { - v_added.remove(pos); - v_added.insert(pos, classes); + ClassesOp::Replace(value) => { + for class in classes { + match self.0.iter().position(|(c, _)| c.eq(&value)) { + Some(pos) => { + self.0.remove(pos); + self.0.insert(pos, (class, ClassType::User)); + } + _ => self.0.push((class, ClassType::User)), } - _ => v_added.push(classes), } - self.added = v_added.join(" "); } - ClassesOp::Reset => self.added = classes.to_owned(), + ClassesOp::Reset => self.0.retain(|(_, t)| t.eq(&ClassType::Default)), - ClassesOp::SetDefault => self.default = classes.to_owned(), - - ClassesOp::SetDefaultIfEmpty => { - if self.default.is_empty() { - self.default = classes.to_owned() + ClassesOp::SetDefault => { + self.0.retain(|(_, t)| t.eq(&ClassType::User)); + let mut pos = 0; + for class in classes { + if self.0.iter().position(|(c, _)| c.eq(&class)).is_none() { + self.0.insert(pos, (class, ClassType::Default)); + pos = pos + 1; + } } } } @@ -95,13 +78,15 @@ impl Classes { // Classes GETTERS. pub fn get(&self) -> Option { - if self.default.is_empty() && self.added.is_empty() { + if self.0.len() == 0 { None } else { Some( - concat_string!(self.default, " ", self.added) - .trim() - .to_owned(), + self.0 + .iter() + .map(|(c, _)| c.to_owned()) + .collect::>() + .join(" "), ) } }