@@ -7,7 +7,7 @@ use crate::visibility::Visibility;
7use crate::{keys, utils};
7use crate::{keys, utils};
8use dodrio::{
8use dodrio::{
9 bumpalo::{self, Bump},
9 bumpalo::{self, Bump},
10− on, Attribute, Node, Render, RootRender, VdomWeak,
10+ Node, Render, RootRender, VdomWeak,
12use serde::{Deserialize, Serialize};
12use serde::{Deserialize, Serialize};
13use std::marker::PhantomData;
13use std::marker::PhantomData;
@@ -140,65 +140,42 @@ impl<C: TodosActions> Todos<C> {
141 'a: 'bump,
141 'a: 'bump,
143− Node::element(
143+ use dodrio::builder::*;
145− "header",
145+ header(bump)
149− value: "header",
146+ .attr("class", "header")
151− [
148+ h1(bump).children([text("todos")]).finish(),
152− Node::element(bump, "h1", [], [], [Node::text("todos")]),
154− bump,
149+ input(bump)
157− on(bump, "input", |root, vdom, event| {
150+ .on("input", |root, vdom, event| {
158− let input = event
151+ let input = event
159− .target()
152+ .target()
160− .unwrap_throw()
153+ .unwrap_throw()
161− .unchecked_into::<web_sys::HtmlInputElement>();
154+ .unchecked_into::<web_sys::HtmlInputElement>();
162− C::update_draft(root, vdom, input.value());
155+ C::update_draft(root, vdom, input.value());
164− on(bump, "keydown", |root, vdom, event| {
157+ .on("keydown", |root, vdom, event| {
165− let event = event.unchecked_into::<web_sys::KeyboardEvent>();
158+ let event = event.unchecked_into::<web_sys::KeyboardEvent>();
166− if event.key_code() == keys::ENTER {
159+ if event.key_code() == keys::ENTER {
167− C::finish_draft(root, vdom);
160+ C::finish_draft(root, vdom);
174− value: "new-todo",
163+ .attr("class", "new-todo")
177− name: "placeholder",
178− value: "What needs to be done?",
164+ .attr("placeholder", "What needs to be done?")
181− name: "autofocus",
165+ .attr("autofocus", "")
186− value: &self.draft,
166+ .attr("value", &self.draft)
195 fn todos_list<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
172 fn todos_list<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
197 'a: 'bump,
174 'a: 'bump,
199− use dodrio::bumpalo::collections::Vec;
176+ use dodrio::{builder::*, bumpalo::collections::Vec};
201− let mut todos = Vec::new_in(bump);
178+ let mut todos = Vec::with_capacity_in(self.todos.len(), bump);
202 todos.extend(
179 todos.extend(
203 self.todos
180 self.todos
@@ -209,91 +186,43 @@ impl<C: TodosActions> Todos<C> {
210 .map(|t| t.render(bump)),
187 .map(|t| t.render(bump)),
212− let todos = todos.into_bump_slice();
189+
214− let mut input_attrs = bumpalo::vec![
218− value: "toggle-all",
222− value: "toggle-all",
233− if self.todos.iter().all(|t| t.is_complete()) {
234− input_attrs.push(Attribute {
239− let input_attrs = input_attrs.into_bump_slice();
243− "section",
190+ section(bump)
247− name: "class",
191+ .attr("class", "main")
248− value: "main",
192+ .attr(
251− name: "visibility",
193+ "visibility",
252− value: if self.todos.is_empty() {
194+ if self.todos.is_empty() {
253− "hidden"
195+ "hidden"
254− } else {
196+ } else {
255− "visible"
197+ "visible"
262− "input",
201+ input(bump)
202+ .attr("class", "toggle-all")
203+ .attr("id", "toggle-all")
204+ .attr("type", "checkbox")
205+ .attr("name", "toggle")
206+ .bool_attr("checked", self.todos.iter().all(|t| t.is_complete()))
263− [on(bump, "click", |root, vdom, _event| {
207+ .on("click", |root, vdom, _event| {
264 C::toggle_all(root, vdom);
208 C::toggle_all(root, vdom);
266− input_attrs,
210+ .finish(),
271− "label",
211+ label(bump)
275− value: "toggle-all",
212+ .attr("for", "toggle-all")
277− [Node::text("Mark all as complete")],
213+ .children([text("Mark all as complete")])
279− Node::element(
215+ ul(bump).attr("class", "todo-list").children(todos).finish(),
293 fn footer<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
220 fn footer<'a, 'bump>(&'a self, bump: &'bump Bump) -> Node<'bump>
295 'a: 'bump,
222 'a: 'bump,
224+ use dodrio::builder::*;
297 let completed_count = self.todos.iter().filter(|t| t.is_complete()).count();
226 let completed_count = self.todos.iter().filter(|t| t.is_complete()).count();
298 let incomplete_count = self.todos.len() - completed_count;
227 let incomplete_count = self.todos.len() - completed_count;
299 let items_left = if incomplete_count == 1 {
228 let items_left = if incomplete_count == 1 {
@@ -303,95 +232,43 @@ impl<C: TodosActions> Todos<C> {
304 let incomplete_count = bumpalo::format!(in bump, "{}", incomplete_count);
233 let incomplete_count = bumpalo::format!(in bump, "{}", incomplete_count);
306− let attrs = if self.todos.is_empty() {
318− &bump.alloc([Attribute {
324 let clear_completed_text = bumpalo::format!(
235 let clear_completed_text = bumpalo::format!(
326 "Clear completed ({})",
237 "Clear completed ({})",
327 self.todos.iter().filter(|t| t.is_complete()).count()
238 self.todos.iter().filter(|t| t.is_complete()).count()
331− bump,
241+ footer(bump)
332− "footer",
242+ .attr("class", "footer")
333− [],
243+ .bool_attr("hidden", self.todos.is_empty())
334− attrs,
244+ .children([
338− "span",
245+ span(bump)
342− value: "todo-count",
246+ .attr("class", "todo-count")
347− "strong",
248+ strong(bump)
350− [Node::text(incomplete_count.into_bump_str())],
249+ .children([text(incomplete_count.into_bump_str())])
352− Node::text(items_left),
251+ text(items_left),
361− value: "filters",
255+ .attr("class", "filters")
364 self.visibility_swap(bump, "#/", Visibility::All),
257 self.visibility_swap(bump, "#/", Visibility::All),
365 self.visibility_swap(bump, "#/active", Visibility::Active),
258 self.visibility_swap(bump, "#/active", Visibility::Active),
366 self.visibility_swap(bump, "#/completed", Visibility::Completed),
259 self.visibility_swap(bump, "#/completed", Visibility::Completed),
371− "button",
262+ button(bump)
372− [on(bump, "click", |root, vdom, _event| {
263+ .on("click", |root, vdom, _event| {
373 C::delete_completed(root, vdom);
264 C::delete_completed(root, vdom);
376− let mut attrs = bumpalo::vec![
380− value: "clear-completed",
266+ .attr("class", "clear-completed")
381− }
267+ .bool_attr("hidden", completed_count == 0)
383− if self.todos.iter().all(|t| !t.is_complete()) {
384− attrs.push(Attribute {
391− [Node::text(clear_completed_text.into_bump_str())],
268+ .children([text(clear_completed_text.into_bump_str())])
397 fn visibility_swap<'a, 'bump>(
274 fn visibility_swap<'a, 'bump>(
@@ -403,34 +280,25 @@ impl<C: TodosActions> Todos<C> {
404 'a: 'bump,
281 'a: 'bump,
406− Node::element(
283+ use dodrio::builder::*;
409− [on(bump, "click", move |root, vdom, _event| {
286+ .on("click", move |root, vdom, _event| {
410 C::change_visibility(root, vdom, target_vis);
287 C::change_visibility(root, vdom, target_vis);
414− bump,
289+ .children([a(bump)
419− name: "href",
290+ .attr("href", url)
420− value: url,
291+ .attr(
423− name: "class",
292+ "class",
424− value: if self.visibility == target_vis {
293+ if self.visibility == target_vis {
425− "selected"
294+ "selected"
426− } else {
295+ } else {
431− [Node::text(target_vis.label())],
299+ .children([text(target_vis.label())])
@@ -439,12 +307,10 @@ impl<C: TodosActions> Render for Todos<C> {
440 'a: 'bump,
308 'a: 'bump,
442− Node::element(
310+ use dodrio::builder::*;
444− "div",
312+ div(bump)
447− [self.header(bump), self.todos_list(bump), self.footer(bump)],
313+ .children([self.header(bump), self.todos_list(bump), self.footer(bump)])