on 00a42e3 help sign in
dodrio/src/builder.rs
884 lines 26 kB history raw
1//! Helpers for building virtual DOM nodes.
3use crate::{Attribute, Listener, Node, RootRender, VdomWeak};
4use bumpalo::Bump;
6/// A virtual DOM element builder.
7///
8/// Typically constructed with element-specific constructors, eg the `div`
9/// function for building `<div>` elements or the `button` function for building
10/// `<button>` elements.
11#[derive(Clone, Debug)]
12pub struct ElementBuilder<'a, Listeners, Attributes, Children>
13where
14 Listeners: 'a + AsRef<[Listener<'a>]>,
15 Attributes: 'a + AsRef<[Attribute<'a>]>,
16 Children: 'a + AsRef<[Node<'a>]>,
18 bump: &'a Bump,
19 tag_name: &'a str,
20 listeners: Listeners,
21 attributes: Attributes,
22 children: Children,
25impl<'a, Listeners, Attributes, Children> ElementBuilder<'a, Listeners, Attributes, Children>
26where
27 Listeners: 'a + AsRef<[Listener<'a>]>,
28 Attributes: 'a + AsRef<[Attribute<'a>]>,
29 Children: 'a + AsRef<[Node<'a>]>,
31 /// Set the listeners for this element.
32 ///
33 /// You can use this method to customize the backing storage for listeners,
34 /// for example to use a fixed-size array instead of the default
35 /// dynamically-sized `bumpalo::collections::Vec`.
36 ///
37 /// Any listeners already added to the builder will be overridden.
38 ///
39 /// # Example
40 ///
41 /// ```no_run
42 /// use dodrio::{builder::*, bumpalo::Bump};
43 ///
44 /// let b = Bump::new();
45 ///
46 /// // Create a `<div>` with a fixed-size array of two listeners.
47 /// let my_div = div(&b)
48 /// .listeners([
49 /// on(&b, "click", |root, vdom, event| {
50 /// // ...
51 /// }),
52 /// on(&b, "dblclick", |root, vdom, event| {
53 /// // ...
54 /// }),
55 /// ])
56 /// .finish();
57 /// ```
58 #[inline]
59 pub fn listeners<L>(self, listeners: L) -> ElementBuilder<'a, L, Attributes, Children>
60 where
61 L: 'a + AsRef<[Listener<'a>]>,
62 {
63 ElementBuilder {
64 bump: self.bump,
65 tag_name: self.tag_name,
66 listeners,
67 attributes: self.attributes,
68 children: self.children,
69 }
70 }
72 /// Set the attributes for this element.
73 ///
74 /// You can use this method to customize the backing storage for attributes,
75 /// for example to use a fixed-size array instead of the default
76 /// dynamically-sized `bumpalo::collections::Vec`.
77 ///
78 /// Any attributes already added to the builder will be overridden.
79 ///
80 /// # Example
81 ///
82 /// ```no_run
83 /// use dodrio::{builder::*, bumpalo::Bump, Attribute};
84 ///
85 /// let b = Bump::new();
86 ///
87 /// // Create a `<div>` with a fixed-size array of two attributes.
88 /// let my_div = div(&b)
89 /// .attributes([
90 /// attr("id", "my-div"),
91 /// attr("class", "notification"),
92 /// ])
93 /// .finish();
94 /// ```
95 #[inline]
96 pub fn attributes<A>(self, attributes: A) -> ElementBuilder<'a, Listeners, A, Children>
97 where
98 A: 'a + AsRef<[Attribute<'a>]>,
99 {
100 ElementBuilder {
101 bump: self.bump,
102 tag_name: self.tag_name,
103 listeners: self.listeners,
104 attributes,
105 children: self.children,
106 }
107 }
109 /// Set the children for this element.
110 ///
111 /// You can use this method to customize the backing storage for children,
112 /// for example to use a fixed-size array instead of the default
113 /// dynamically-sized `bumpalo::collections::Vec`.
114 ///
115 /// Any children already added to the builder will be overridden.
116 ///
117 /// # Example
118 ///
119 /// ```no_run
120 /// use dodrio::{builder::*, bumpalo::Bump};
121 ///
122 /// let b = Bump::new();
123 ///
124 /// // Create a `<div>` with a fixed-size array of two `<span>` children.
125 /// let my_div = div(&b)
126 /// .children([
127 /// span(&b).finish(),
128 /// span(&b).finish(),
129 /// ])
130 /// .finish();
131 /// ```
132 #[inline]
133 pub fn children<C>(self, children: C) -> ElementBuilder<'a, Listeners, Attributes, C>
134 where
135 C: 'a + AsRef<[Node<'a>]>,
136 {
137 ElementBuilder {
138 bump: self.bump,
139 tag_name: self.tag_name,
140 listeners: self.listeners,
141 attributes: self.attributes,
142 children,
143 }
144 }
146 /// Create the virtual DOM node described by this builder.
147 ///
148 /// # Example
149 ///
150 /// ```no_run
151 /// use dodrio::{builder::*, bumpalo::Bump, Node};
152 ///
153 /// let b = Bump::new();
154 ///
155 /// // Start with a builder...
156 /// let builder: ElementBuilder<_, _, _> = div(&b);
157 ///
158 /// // ...and finish it to create a virtual DOM node!
159 /// let my_div: Node = builder.finish();
160 /// ```
161 #[inline]
162 pub fn finish(self) -> Node<'a> {
163 Node::element(
164 self.bump,
165 self.tag_name,
166 self.listeners,
167 self.attributes,
168 self.children,
169 )
170 }
173impl<'a, Attributes, Children>
174 ElementBuilder<'a, bumpalo::collections::Vec<'a, Listener<'a>>, Attributes, Children>
175where
176 Attributes: 'a + AsRef<[Attribute<'a>]>,
177 Children: 'a + AsRef<[Node<'a>]>,
179 /// Add a new event listener to this element.
180 ///
181 /// The `event` string specifies which event will be listened for. The
182 /// `callback` function is the function that will be invoked if the
183 /// specified event occurs.
184 ///
185 /// # Example
186 ///
187 /// ```no_run
188 /// use dodrio::{builder::*, bumpalo::Bump};
189 ///
190 /// let b = Bump::new();
191 ///
192 /// // A button that does something when clicked!
193 /// let my_button = button(&b)
194 /// .on("click", |root, vdom, event| {
195 /// // ...
196 /// })
197 /// .finish();
198 /// ```
199 #[inline]
200 pub fn on<F>(mut self, event: &'a str, callback: F) -> Self
201 where
202 F: 'static + Fn(&mut dyn RootRender, VdomWeak, web_sys::Event),
203 {
204 self.listeners.push(Listener {
205 event,
206 callback: self.bump.alloc(callback),
207 });
208 self
209 }
212impl<'a, Listeners, Children>
213 ElementBuilder<'a, Listeners, bumpalo::collections::Vec<'a, Attribute<'a>>, Children>
214where
215 Listeners: 'a + AsRef<[Listener<'a>]>,
216 Children: 'a + AsRef<[Node<'a>]>,
218 /// Add a new attribute to this element.
219 ///
220 /// # Example
221 ///
222 /// ```no_run
223 /// use dodrio::{builder::*, bumpalo::Bump};
224 ///
225 /// let b = Bump::new();
226 ///
227 /// // Create the `<div id="my-div"/>` element.
228 /// let my_div = div(&b).attr("id", "my-div").finish();
229 /// ```
230 #[inline]
231 pub fn attr(mut self, name: &'a str, value: &'a str) -> Self {
232 self.attributes.push(Attribute { name, value });
233 self
234 }
236 /// Conditionally add a "boolean-style" attribute to this element.
237 ///
238 /// If the `should_add` parameter is true, then adds an attribute with the
239 /// given `name` and an empty string value. If the `should_add` parameter is
240 /// false, then the attribute is not added.
241 ///
242 /// This method is useful for attributes whose semantics are defined by
243 /// whether or not the attribute is present or not, and whose value is
244 /// ignored. Example attributes like this include:
245 ///
246 /// * `checked`
247 /// * `hidden`
248 /// * `selected`
249 ///
250 /// # Example
251 ///
252 /// ```no_run
253 /// use dodrio::{builder::*, bumpalo::Bump};
254 /// use js_sys::Math;
255 ///
256 /// let b = Bump::new();
257 ///
258 /// // Create the `<div>` that is randomly hidden 50% of the time.
259 /// let my_div = div(&b)
260 /// .bool_attr("hidden", Math::random() >= 0.5)
261 /// .finish();
262 /// ```
263 pub fn bool_attr(mut self, name: &'a str, should_add: bool) -> Self {
264 if should_add {
265 self.attributes.push(Attribute { name, value: "" });
266 }
267 self
268 }
271impl<'a, Listeners, Attributes>
272 ElementBuilder<'a, Listeners, Attributes, bumpalo::collections::Vec<'a, Node<'a>>>
273where
274 Listeners: 'a + AsRef<[Listener<'a>]>,
275 Attributes: 'a + AsRef<[Attribute<'a>]>,
277 /// Add a new child to this element.
278 ///
279 /// # Example
280 ///
281 /// ```no_run
282 /// use dodrio::{builder::*, bumpalo::Bump};
283 /// use js_sys::Math;
284 ///
285 /// let b = Bump::new();
286 ///
287 /// // Create `<p><span></span></p>`.
288 /// let my_div = p(&b)
289 /// .child(span(&b).finish())
290 /// .finish();
291 /// ```
292 #[inline]
293 pub fn child(mut self, child: Node<'a>) -> Self {
294 self.children.push(child);
295 self
296 }
299macro_rules! builder_constructors {
300 ( $(
301 $(#[$attr:meta])*
302 $name:ident;
303 )* ) => {
304 $(
305 $(#[$attr])*
306 #[inline]
307 pub fn $name<'a>(
308 bump: &'a Bump,
309 ) -> ElementBuilder<
310 'a,
311 bumpalo::collections::Vec<'a, Listener<'a>>,
312 bumpalo::collections::Vec<'a, Attribute<'a>>,
313 bumpalo::collections::Vec<'a, Node<'a>>,
314 > {
315 ElementBuilder {
316 bump,
317 tag_name: stringify!($name),
318 listeners: bumpalo::collections::Vec::new_in(bump),
319 attributes: bumpalo::collections::Vec::new_in(bump),
320 children: bumpalo::collections::Vec::new_in(bump),
321 }
322 }
323 )*
324 }
327// Organized in the same order as
328// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
329//
330// Does not include obsolete elements.
331builder_constructors! {
332 // Document metadata
334 /// Build a
335 /// [`<base>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base)
336 /// element.
337 base;
338 /// Build a
339 /// [`<head>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head)
340 /// element.
341 head;
342 /// Build a
343 /// [`<link>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link)
344 /// element.
345 link;
346 /// Build a
347 /// [`<meta>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta)
348 /// element.
349 meta;
350 /// Build a
351 /// [`<style>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style)
352 /// element.
353 style;
354 /// Build a
355 /// [`<title>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title)
356 /// element.
357 title;
359 // Sectioning root
361 /// Build a
362 /// [`<body>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body)
363 /// element.
364 body;
366 // Content sectioning
368 /// Build a
369 /// [`<address>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address)
370 /// element.
371 address;
372 /// Build a
373 /// [`<article>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article)
374 /// element.
375 article;
376 /// Build a
377 /// [`<aside>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside)
378 /// element.
379 aside;
380 /// Build a
381 /// [`<footer>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer)
382 /// element.
383 footer;
384 /// Build a
385 /// [`<header>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header)
386 /// element.
387 header;
388 /// Build a
389 /// [`<h1>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1)
390 /// element.
391 h1;
392 /// Build a
393 /// [`<h2>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2)
394 /// element.
395 h2;
396 /// Build a
397 /// [`<h3>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3)
398 /// element.
399 h3;
400 /// Build a
401 /// [`<h4>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4)
402 /// element.
403 h4;
404 /// Build a
405 /// [`<h5>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5)
406 /// element.
407 h5;
408 /// Build a
409 /// [`<h6>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6)
410 /// element.
411 h6;
412 /// Build a
413 /// [`<hgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup)
414 /// element.
415 hgroup;
416 /// Build a
417 /// [`<main>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main)
418 /// element.
419 main;
420 /// Build a
421 /// [`<nav>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav)
422 /// element.
423 nav;
424 /// Build a
425 /// [`<section>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)
426 /// element.
427 section;
429 // Text content
431 /// Build a
432 /// [`<blockquote>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote)
433 /// element.
434 blockquote;
435 /// Build a
436 /// [`<dd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd)
437 /// element.
438 dd;
439 /// Build a
440 /// [`<div>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div)
441 /// element.
442 div;
443 /// Build a
444 /// [`<dl>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl)
445 /// element.
446 dl;
447 /// Build a
448 /// [`<dt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt)
449 /// element.
450 dt;
451 /// Build a
452 /// [`<figcaption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption)
453 /// element.
454 figcaption;
455 /// Build a
456 /// [`<figure>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure)
457 /// element.
458 figure;
459 /// Build a
460 /// [`<hr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr)
461 /// element.
462 hr;
463 /// Build a
464 /// [`<li>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li)
465 /// element.
466 li;
467 /// Build a
468 /// [`<ol>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol)
469 /// element.
470 ol;
471 /// Build a
472 /// [`<p>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p)
473 /// element.
474 p;
475 /// Build a
476 /// [`<pre>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre)
477 /// element.
478 pre;
479 /// Build a
480 /// [`<ul>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul)
481 /// element.
482 ul;
484 // Inline text semantics
486 /// Build a
487 /// [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)
488 /// element.
489 a;
490 /// Build a
491 /// [`<abbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr)
492 /// element.
493 abbr;
494 /// Build a
495 /// [`<b>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b)
496 /// element.
497 b;
498 /// Build a
499 /// [`<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi)
500 /// element.
501 bdi;
502 /// Build a
503 /// [`<bdo>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo)
504 /// element.
505 bdo;
506 /// Build a
507 /// [`<br>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br)
508 /// element.
509 br;
510 /// Build a
511 /// [`<cite>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite)
512 /// element.
513 cite;
514 /// Build a
515 /// [`<code>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code)
516 /// element.
517 code;
518 /// Build a
519 /// [`<data>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data)
520 /// element.
521 data;
522 /// Build a
523 /// [`<dfn>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn)
524 /// element.
525 dfn;
526 /// Build a
527 /// [`<em>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em)
528 /// element.
529 em;
530 /// Build a
531 /// [`<i>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i)
532 /// element.
533 i;
534 /// Build a
535 /// [`<kbd>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd)
536 /// element.
537 kbd;
538 /// Build a
539 /// [`<mark>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark)
540 /// element.
541 mark;
542 /// Build a
543 /// [`<q>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q)
544 /// element.
545 q;
546 /// Build a
547 /// [`<rb>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rb)
548 /// element.
549 rb;
550 /// Build a
551 /// [`<rp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp)
552 /// element.
553 rp;
554 /// Build a
555 /// [`<rt>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt)
556 /// element.
557 rt;
558 /// Build a
559 /// [`<rtc>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rtc)
560 /// element.
561 rtc;
562 /// Build a
563 /// [`<ruby>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby)
564 /// element.
565 ruby;
566 /// Build a
567 /// [`<s>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s)
568 /// element.
569 s;
570 /// Build a
571 /// [`<samp>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp)
572 /// element.
573 samp;
574 /// Build a
575 /// [`<small>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small)
576 /// element.
577 small;
578 /// Build a
579 /// [`<span>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span)
580 /// element.
581 span;
582 /// Build a
583 /// [`<strong>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong)
584 /// element.
585 strong;
586 /// Build a
587 /// [`<sub>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub)
588 /// element.
589 sub;
590 /// Build a
591 /// [`<sup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup)
592 /// element.
593 sup;
594 /// Build a
595 /// [`<time>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time)
596 /// element.
597 time;
598 /// Build a
599 /// [`<u>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u)
600 /// element.
601 u;
602 /// Build a
603 /// [`<var>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var)
604 /// element.
605 var;
606 /// Build a
607 /// [`<wbr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr)
608 /// element.
609 wbr;
611 // Image and multimedia
613 /// Build a
614 /// [`<area>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area)
615 /// element.
616 area;
617 /// Build a
618 /// [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
619 /// element.
620 audio;
621 /// Build a
622 /// [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img)
623 /// element.
624 img;
625 /// Build a
626 /// [`<map>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map)
627 /// element.
628 map;
629 /// Build a
630 /// [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track)
631 /// element.
632 track;
633 /// Build a
634 /// [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video)
635 /// element.
636 video;
638 // Embedded content
640 /// Build a
641 /// [`<embed>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed)
642 /// element.
643 embed;
644 /// Build a
645 /// [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe)
646 /// element.
647 iframe;
648 /// Build a
649 /// [`<object>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object)
650 /// element.
651 object;
652 /// Build a
653 /// [`<param>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/param)
654 /// element.
655 param;
656 /// Build a
657 /// [`<picture>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture)
658 /// element.
659 picture;
660 /// Build a
661 /// [`<source>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source)
662 /// element.
663 source;
665 // Scripting
667 /// Build a
668 /// [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas)
669 /// element.
670 canvas;
671 /// Build a
672 /// [`<noscript>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript)
673 /// element.
674 noscript;
675 /// Build a
676 /// [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)
677 /// element.
678 script;
680 // Demarcating edits
682 /// Build a
683 /// [`<del>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del)
684 /// element.
685 del;
686 /// Build a
687 /// [`<ins>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins)
688 /// element.
689 ins;
691 // Table content
693 /// Build a
694 /// [`<caption>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption)
695 /// element.
696 caption;
697 /// Build a
698 /// [`<col>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/col)
699 /// element.
700 col;
701 /// Build a
702 /// [`<colgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/colgroup)
703 /// element.
704 colgroup;
705 /// Build a
706 /// [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table)
707 /// element.
708 table;
709 /// Build a
710 /// [`<tbody>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody)
711 /// element.
712 tbody;
713 /// Build a
714 /// [`<td>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)
715 /// element.
716 td;
717 /// Build a
718 /// [`<tfoot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot)
719 /// element.
720 tfoot;
721 /// Build a
722 /// [`<th>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th)
723 /// element.
724 th;
725 /// Build a
726 /// [`<thead>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead)
727 /// element.
728 thead;
729 /// Build a
730 /// [`<tr>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr)
731 /// element.
732 tr;
734 // Forms
736 /// Build a
737 /// [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)
738 /// element.
739 button;
740 /// Build a
741 /// [`<datalist>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)
742 /// element.
743 datalist;
744 /// Build a
745 /// [`<fieldset>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset)
746 /// element.
747 fieldset;
748 /// Build a
749 /// [`<form>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form)
750 /// element.
751 form;
752 /// Build a
753 /// [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)
754 /// element.
755 input;
756 /// Build a
757 /// [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
758 /// element.
759 label;
760 /// Build a
761 /// [`<legend>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend)
762 /// element.
763 legend;
764 /// Build a
765 /// [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter)
766 /// element.
767 meter;
768 /// Build a
769 /// [`<optgroup>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup)
770 /// element.
771 optgroup;
772 /// Build a
773 /// [`<option>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option)
774 /// element.
775 option;
776 /// Build a
777 /// [`<output>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output)
778 /// element.
779 output;
780 /// Build a
781 /// [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress)
782 /// element.
783 progress;
784 /// Build a
785 /// [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select)
786 /// element.
787 select;
788 /// Build a
789 /// [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea)
790 /// element.
791 textarea;
793 // Interactive elements
795 /// Build a
796 /// [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details)
797 /// element.
798 details;
799 /// Build a
800 /// [`<dialog>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog)
801 /// element.
802 dialog;
803 /// Build a
804 /// [`<menu>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu)
805 /// element.
806 menu;
807 /// Build a
808 /// [`<menuitem>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menuitem)
809 /// element.
810 menuitem;
811 /// Build a
812 /// [`<summary>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary)
813 /// element.
814 summary;
816 // Web components
818 /// Build a
819 /// [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot)
820 /// element.
821 slot;
822 /// Build a
823 /// [`<template>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template)
824 /// element.
825 template;
828/// Construct a text node.
829///
830/// This is `dodrio`'s virtual DOM equivalent of `document.createTextNode`.
831///
832/// # Example
833///
834/// ```no_run
835/// use dodrio::builder::*;
836///
837/// let my_text = text("hello, dodrio!");
838/// ```
839#[inline]
840pub fn text<'a>(contents: &'a str) -> Node<'a> {
841 Node::text(contents)
844/// Construct an attribute for an element.
845///
846/// # Example
847///
848/// This example creates the `id="my-id"` for some element like `<div
849/// id="my-id"/>`.
850///
851/// ```no_run
852/// use dodrio::builder::*;
853///
854/// let my_id_attr = attr("id", "my-id");
855/// ```
856pub fn attr<'a>(name: &'a str, value: &'a str) -> Attribute<'a> {
857 Attribute { name, value }
860/// Create an event listener.
861///
862/// `event` is the type of event to listen for, e.g. `"click"`. The `callback`
863/// is the function that will be invoked when the event occurs.
864///
865/// # Example
866///
867/// ```no_run
868/// use dodrio::{builder::*, bumpalo::Bump};
869///
870/// let b = Bump::new();
871///
872/// let listener = on(&b, "click", |root, vdom, event| {
873/// // do something when a click happens...
874/// });
875/// ```
876pub fn on<'a, F>(bump: &'a Bump, event: &'a str, callback: F) -> Listener<'a>
877where
878 F: Fn(&mut dyn RootRender, VdomWeak, web_sys::Event) + 'static,
880 Listener {
881 event,
882 callback: bump.alloc(callback),
883 }