use crate::{
element::{Element, HtmlElement, HtmlElementConfig},
tags::TagType,
};
use super::field::{AsHtmlConfig, InputFieldConfig};
pub struct SelectInputConfigs {
pub auto_complete: Option<String>,
pub form: Option<String>,
pub size: Option<usize>,
pub multiple: Option<bool>,
pub auto_focus: Option<bool>,
pub disabled: Option<bool>,
pub required: Option<bool>,
}
pub enum Options {
OptionGroup(SelectOptionGroup, HtmlElementConfig),
Option(SelectOption, HtmlElementConfig),
}
pub struct SelectOptionGroup {
pub content: Vec<(SelectOption, HtmlElementConfig)>,
pub label: Option<String>,
pub disabled: Option<bool>,
}
pub struct SelectOption {
pub value: String,
pub label: String,
pub disabled: Option<bool>,
pub selected: Option<bool>,
}
pub fn create_labeled_select(
html_configs: InputFieldConfig,
select_configs: SelectInputConfigs,
values: Vec<Options>,
) -> Element {
let label = Element::Element(HtmlElement::new(
TagType::Label,
html_configs
.label_config
.set_attribute("for".to_string(), Some(html_configs.id.clone())),
)) + Element::Text(html_configs.label);
let configs = select_configs.set_html_configs(
html_configs
.field_config
.set_attribute("id".to_string(), Some(html_configs.id))
.set_attribute("name".to_string(), Some(html_configs.name)),
);
let mut select = Element::Element(HtmlElement::new(TagType::Select, configs));
for option in values {
select += match option {
Options::OptionGroup(select_option_group, html_element_config) => {
create_option_group(select_option_group, html_element_config)
}
Options::Option(select_option, html_element_config) => {
create_option(select_option, html_element_config)
}
};
}
Element::Element(HtmlElement::new(
TagType::Div,
HtmlElementConfig::new_empty(),
)) + label
+ select
}
pub fn create_select(
html_configs: InputFieldConfig,
select_configs: SelectInputConfigs,
values: Vec<Options>,
) -> Element {
let configs = select_configs.set_html_configs(
html_configs
.field_config
.set_attribute("id".to_string(), Some(html_configs.id))
.set_attribute("name".to_string(), Some(html_configs.name)),
);
let mut select = Element::Element(HtmlElement::new(TagType::Select, configs));
for option in values {
select += match option {
Options::OptionGroup(select_option_group, html_element_config) => {
create_option_group(select_option_group, html_element_config)
}
Options::Option(select_option, html_element_config) => {
create_option(select_option, html_element_config)
}
};
}
Element::Element(HtmlElement::new(
TagType::Div,
HtmlElementConfig::new_empty(),
)) + select
}
pub fn create_option_group(option_group: SelectOptionGroup, configs: HtmlElementConfig) -> Element {
let mut configs = configs;
if option_group.label.is_some() {
configs = configs.set_attribute("label".to_string(), option_group.label);
}
if let Some(disabled) = option_group.disabled {
if disabled {
configs = configs.set_attribute("disabled".to_string(), None);
}
}
let mut optgroup = Element::Element(HtmlElement::new(TagType::OptGroup, configs));
for (option, option_configs) in option_group.content {
optgroup += create_option(option, option_configs);
}
optgroup
}
pub fn create_option(option: SelectOption, configs: HtmlElementConfig) -> Element {
let mut configs = configs.set_attribute("value".to_string(), Some(option.value));
if let Some(disabled) = option.disabled {
if disabled {
configs = configs.set_attribute("disabled".to_string(), None);
}
}
if let Some(selected) = option.selected {
if selected {
configs = configs.set_attribute("selected".to_string(), None);
}
}
Element::Element(HtmlElement::new(TagType::Option, configs)) + Element::Text(option.label)
}
impl SelectInputConfigs {
pub fn new() -> Self {
Self::default()
}
pub fn with_auto_complete(mut self, auto_complete: String) -> Self {
self.auto_complete = Some(auto_complete);
self
}
pub fn without_auto_complete(mut self) -> Self {
self.auto_complete = None;
self
}
pub fn with_form(mut self, form: String) -> Self {
self.form = Some(form);
self
}
pub fn without_form(mut self) -> Self {
self.form = None;
self
}
pub fn with_size(mut self, size: usize) -> Self {
self.size = Some(size);
self
}
pub fn without_size(mut self) -> Self {
self.size = None;
self
}
pub fn with_multiple(mut self, multiple: bool) -> Self {
self.multiple = Some(multiple);
self
}
pub fn without_multiple(mut self) -> Self {
self.multiple = None;
self
}
pub fn with_auto_focus(mut self, auto_focus: bool) -> Self {
self.auto_focus = Some(auto_focus);
self
}
pub fn without_auto_focus(mut self) -> Self {
self.auto_focus = None;
self
}
pub fn with_disabled(mut self, disabled: bool) -> Self {
self.disabled = Some(disabled);
self
}
pub fn without_disabled(mut self) -> Self {
self.disabled = None;
self
}
pub fn with_required(mut self, required: bool) -> Self {
self.required = Some(required);
self
}
pub fn without_required(mut self) -> Self {
self.required = None;
self
}
}
impl SelectOptionGroup {
pub fn new() -> Self {
Self::default()
}
pub fn with_option(mut self, option: (SelectOption, HtmlElementConfig)) -> Self {
self.content.push(option);
self
}
pub fn with_content<T>(mut self, content: T) -> Self
where
T: Iterator<Item = (SelectOption, HtmlElementConfig)>,
{
self.content.extend(content);
self
}
pub fn with_label(mut self, label: String) -> Self {
self.label = Some(label);
self
}
pub fn without_label(mut self) -> Self {
self.label = None;
self
}
pub fn with_disabled(mut self, disabled: bool) -> Self {
self.disabled = Some(disabled);
self
}
pub fn without_disabled(mut self) -> Self {
self.disabled = None;
self
}
}
impl SelectOption {
pub fn new(value: String, label: String) -> Self {
Self {
value,
label,
..Self::default()
}
}
pub fn set_label(mut self, label: String) -> Self {
self.label = label;
self
}
pub fn set_value(mut self, value: String) -> Self {
self.value = value;
self
}
pub fn with_disabled(mut self, disabled: bool) -> Self {
self.disabled = Some(disabled);
self
}
pub fn without_disabled(mut self) -> Self {
self.disabled = None;
self
}
pub fn with_selected(mut self, selected: bool) -> Self {
self.selected = Some(selected);
self
}
pub fn without_selected(mut self) -> Self {
self.selected = None;
self
}
}
impl AsHtmlConfig for SelectInputConfigs {
fn set_html_configs(&self, mut configs: HtmlElementConfig) -> HtmlElementConfig {
if self.auto_complete.is_some() {
configs = configs.set_attribute("autocomplete".to_string(), self.auto_complete.clone());
}
if self.form.is_some() {
configs = configs.set_attribute("form".to_string(), self.form.clone());
}
if let Some(size) = self.size {
configs = configs.set_attribute("size".to_string(), Some(size.to_string()));
}
if let Some(multiple) = self.multiple {
if multiple {
configs = configs.set_attribute("multiple".to_string(), None);
}
}
if let Some(auto_focus) = self.auto_focus {
if auto_focus {
configs = configs.set_attribute("autofocus".to_string(), None);
}
}
if let Some(disabled) = self.disabled {
if disabled {
configs = configs.set_attribute("disabled".to_string(), None);
}
}
if let Some(required) = self.required {
if required {
configs = configs.set_attribute("required".to_string(), None);
}
}
configs
}
}
impl Default for SelectInputConfigs {
fn default() -> Self {
Self {
auto_complete: None,
form: None,
size: None,
multiple: None,
auto_focus: None,
disabled: None,
required: None,
}
}
}
impl Default for SelectOptionGroup {
fn default() -> Self {
Self {
content: Default::default(),
label: Default::default(),
disabled: Default::default(),
}
}
}
impl Default for SelectOption {
fn default() -> Self {
Self {
value: String::new(),
label: String::new(),
disabled: None,
selected: None,
}
}
}