use super::{MJAccordionElement, NAME};
use crate::helper::condition::negation_conditional_tag;
use crate::helper::tag::Tag;
use crate::mj_accordion_text::MJAccordionText;
use crate::mj_accordion_title::MJAccordionTitle;
use crate::prelude::render::{Error, Header, Options, Render, Renderable};
use std::cell::{Ref, RefCell};
use std::collections::HashMap;
use std::rc::Rc;
const CHILDREN_ATTRIBUTES: [&str; 9] = [
"border",
"icon-align",
"icon-width",
"icon-height",
"icon-position",
"icon-wrapped-url",
"icon-wrapped-alt",
"icon-unwrapped-url",
"icon-unwrapped-alt",
];
struct MJAccordionElementRender<'e, 'h> {
header: Rc<RefCell<Header<'h>>>,
element: &'e MJAccordionElement,
extra: HashMap<String, String>,
}
impl<'e, 'h> MJAccordionElementRender<'e, 'h> {
fn render_title(&self, opts: &Options) -> Result<String, Error> {
if let Some(ref child) = self.element.children.title {
let mut renderer = child.renderer(Rc::clone(&self.header));
CHILDREN_ATTRIBUTES.iter().for_each(|name| {
renderer.maybe_add_extra_attribute(name, self.attribute(name));
});
renderer.render(opts)
} else {
let child = MJAccordionTitle::default();
let mut renderer = child.renderer(Rc::clone(&self.header));
CHILDREN_ATTRIBUTES.iter().for_each(|name| {
renderer.maybe_add_extra_attribute(name, self.attribute(name));
});
renderer.render(opts)
}
}
fn render_text(&self, opts: &Options) -> Result<String, Error> {
if let Some(ref child) = self.element.children.text {
let mut renderer = child.renderer(Rc::clone(&self.header));
CHILDREN_ATTRIBUTES.iter().for_each(|name| {
renderer.maybe_add_extra_attribute(name, self.attribute(name));
});
renderer.render(opts)
} else {
let child = MJAccordionText::default();
let mut renderer = child.renderer(Rc::clone(&self.header));
CHILDREN_ATTRIBUTES.iter().for_each(|name| {
renderer.maybe_add_extra_attribute(name, self.attribute(name));
});
renderer.render(opts)
}
}
fn render_children(&self, opts: &Options) -> Result<String, Error> {
Ok(self.render_title(opts)? + &self.render_text(opts)?)
}
}
impl<'e, 'h> Render<'h> for MJAccordionElementRender<'e, 'h> {
fn add_extra_attribute(&mut self, key: &str, value: &str) {
self.extra.insert(key.to_string(), value.to_string());
}
fn extra_attributes(&self) -> Option<&HashMap<String, String>> {
Some(&self.extra)
}
fn attributes(&self) -> Option<&HashMap<String, String>> {
Some(&self.element.attributes)
}
fn tag(&self) -> Option<&str> {
Some(NAME)
}
fn header(&self) -> Ref<Header<'h>> {
self.header.borrow()
}
fn render(&self, opts: &Options) -> Result<String, Error> {
let input = negation_conditional_tag(
Tag::new("input")
.add_attribute("type", "checkbox")
.add_class("mj-accordion-checkbox")
.add_style("display", "none")
.closed(),
);
let div = Tag::div().render(self.render_children(opts)?);
let label = Tag::new("label")
.add_class("mj-accordion-element")
.add_style("font-size", "13px")
.maybe_add_style("font-family", self.attribute("font-family"))
.render(input + &div);
let td = Tag::td()
.add_style("padding", "0px")
.maybe_add_style("background-color", self.attribute("background-color"))
.render(label);
let tr = Tag::tr()
.maybe_add_class(self.attribute("css-class"))
.render(td);
Ok(tr)
}
}
impl<'r, 'e: 'r, 'h: 'r> Renderable<'r, 'e, 'h> for MJAccordionElement {
fn renderer(&'e self, header: Rc<RefCell<Header<'h>>>) -> Box<dyn Render<'h> + 'r> {
Box::new(MJAccordionElementRender::<'e, 'h> {
element: self,
header,
extra: HashMap::new(),
})
}
}