silkenweb/elements.rs
1//! HTML element types.
2//!
3//! Each HTML element has an associated struct. For example, the `<a>` element
4//! is represented by [`html::A`]. The constructor is a free function of the
5//! same name, so you can write `a()` rather than `A::new()`. There are methods
6//! for each attribute and event. Event methods are prefixed with `on_`. For
7//! example:
8//!
9//! ```no_run
10//! # use silkenweb::{elements::html::{a, A}, elements::{HtmlElement, ElementEvents}};
11//! let link: A = a()
12//! .href("https://example.com/")
13//! .on_click(|event, element| {});
14//! ```
15//!
16//! The element type implements various traits, including:
17//!
18//! - [`Element`]
19//! - [`HtmlElement`]
20//! - [`HtmlElementEvents`]
21//! - [`ElementEvents`]
22//! - [`ParentElement`] (if it is a parent element)
23//! - [`ShadowRootParent`] (if it's allowed to have a shadow root attached)
24//!
25//! Each element can be frozen, making it immutable, using the `freeze` method.
26//!
27//! [`ParentElement`]: crate::node::element::ParentElement
28//! [`ShadowRootParent`]: crate::node::element::ShadowRootParent
29
30use std::{marker::PhantomData, ops::Deref};
31
32use wasm_bindgen::{JsCast, JsValue};
33
34use crate::node::element::Element;
35
36pub mod html;
37pub mod svg;
38
39/// Wrap a [`web_sys::CustomEvent`].
40///
41/// This is used when defining custom HTML elements to represent web components.
42/// See [`custom_html_element`] for more details.
43#[derive(Clone)]
44pub struct CustomEvent<T>(web_sys::CustomEvent, PhantomData<T>);
45
46impl<T: JsCast> CustomEvent<T> {
47 /// The original event.
48 pub fn event(&self) -> &web_sys::CustomEvent {
49 &self.0
50 }
51
52 /// The event detail, downcast into `T`.
53 ///
54 /// The downcast is unchecked.
55 pub fn detail(&self) -> T {
56 self.0.detail().unchecked_into()
57 }
58}
59
60impl<T> Deref for CustomEvent<T> {
61 type Target = web_sys::CustomEvent;
62
63 fn deref(&self) -> &Self::Target {
64 &self.0
65 }
66}
67
68impl<T> From<JsValue> for CustomEvent<T> {
69 fn from(src: JsValue) -> Self {
70 Self(src.into(), PhantomData)
71 }
72}
73
74impl<T> From<web_sys::CustomEvent> for CustomEvent<T> {
75 fn from(src: web_sys::CustomEvent) -> Self {
76 Self(src, PhantomData)
77 }
78}
79
80macro_rules! global_attributes {
81 ($($t:tt)*) => {
82 attributes![
83 [
84 attribute_parent = (),
85 attribute_doc_macro = global_attribute_doc
86 ]
87
88 $($t)*
89 ];
90 };
91}
92
93macro_rules! global_attribute_doc {
94 ($element:expr, $name:expr) => {
95 concat!(
96 "The Global [",
97 $name,
98 "](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#attr-",
99 $name,
100 ") Attribute"
101 )
102 };
103}
104
105/// An HTML element
106///
107/// Methods for setting attributes specific to HTML elements
108pub trait HtmlElement: Element {
109 global_attributes![
110 /// Provides a hint for generating a keyboard shortcut for the current
111 /// element. This attribute consists of a space-separated list of
112 /// characters. The browser should use the first one that exists on the
113 /// computer keyboard layout.
114 accesskey: String,
115 /// Controls whether and how text input is automatically capitalized as
116 /// it is entered/edited by the user. It can have the following values:
117 ///
118 /// - off or none, no autocapitalization is applied (all letters default
119 /// to lowercase)
120 /// - on or sentences, the first letter of each sentence defaults to a
121 /// capital letter; all other letters default to lowercase
122 /// - words, the first letter of each word defaults to a capital letter;
123 /// all other letters default to lowercase
124 /// - characters, all letters should default to uppercase
125 autocapitalize: String,
126 /// Indicates that an element is to be focused on page load, or as soon
127 /// as the `<dialog>` it is part of is displayed. This attribute is a
128 /// boolean, initially false.
129 autofocus: bool,
130 /// An enumerated attribute indicating if the element should be
131 /// editable by the user. If so, the browser modifies its widget to
132 /// allow editing. The attribute must take one of the following values:
133 ///
134 /// - true or the empty string, which indicates that the element must be
135 /// editable;
136 /// - false, which indicates that the element must not be editable.
137 contenteditable: String,
138 /// The id of a `<menu>` to use as the contextual menu for this element.
139 contextmenu: String,
140 /// An enumerated attribute indicating the directionality of the
141 /// element's text. It can have the following values:
142 ///
143 /// - ltr, which means left to right and is to be used for languages
144 /// that are written from the left to the right (like English);
145 /// - rtl, which means right to left and is to be used for languages
146 /// that are written from the right to the left (like Arabic);
147 /// - auto, which lets the user agent decide. It uses a basic algorithm
148 /// as it parses the characters inside the element until it finds a
149 /// character with a strong directionality, then it applies that
150 /// directionality to the whole element.
151 dir: String,
152 /// An enumerated attribute indicating whether the element can be
153 /// dragged, using the Drag and Drop API. It can have the following
154 /// values:
155 ///
156 /// - true, which indicates that the element may be dragged
157 /// - false, which indicates that the element may not be dragged.
158 draggable: String,
159 /// Hints what action label (or icon) to present for the enter key on
160 /// virtual keyboards.
161 enterkeyhint: String,
162 /// Used to transitively export shadow parts from a nested shadow tree
163 /// into a containing light tree.
164 exportparts: String,
165 /// A Boolean attribute indicates that the element is not yet, or is no
166 /// longer, relevant. For example, it can be used to hide elements of
167 /// the page that can't be used until the login process has been
168 /// completed. The browser won't render such elements. This attribute
169 /// must not be used to hide content that could legitimately be shown.
170 hidden: bool,
171 /// Defines a unique identifier (ID) which must be unique in the whole
172 /// document. Its purpose is to identify the element when linking (using
173 /// a fragment identifier), scripting, or styling (with CSS).
174 id: String,
175 /// Provides a hint to browsers as to the type of virtual keyboard
176 /// configuration to use when editing this element or its contents. Used
177 /// primarily on `<input>` elements, but is usable on any element while
178 /// in contenteditable mode.
179 inputmode: String,
180 /// Allows you to specify that a standard HTML element should behave
181 /// like a registered custom built-in element (see Using custom elements
182 /// for more details).
183 is: String,
184 /// The unique, global identifier of an item.
185 itemid: String,
186 /// Used to add properties to an item. Every HTML element may have an
187 /// itemprop attribute specified, where an itemprop consists of a name
188 /// and value pair.
189 itemprop: String,
190 /// Properties that are not descendants of an element with the itemscope
191 /// attribute can be associated with the item using an itemref. It
192 /// provides a list of element ids (not itemids) with additional
193 /// properties elsewhere in the document.
194 itemref: String,
195 /// itemscope (usually) works along with itemtype to specify that the
196 /// HTML contained in a block is about a particular item. itemscope
197 /// creates the Item and defines the scope of the itemtype associated
198 /// with it. itemtype is a valid URL of a vocabulary (such as
199 /// schema.org) that describes the item and its properties context.
200 itemscope: String,
201 /// Specifies the URL of the vocabulary that will be used to define
202 /// itemprops (item properties) in the data structure. itemscope is used
203 /// to set the scope of where in the data structure the vocabulary set
204 /// by itemtype will be active.
205 itemtype: String,
206 /// Helps define the language of an element: the language that
207 /// non-editable elements are in, or the language that editable elements
208 /// should be written in by the user. The attribute contains one
209 /// “language tag” (made of hyphen-separated “language subtags”) in the
210 /// format defined in RFC 5646: Tags for Identifying Languages (also
211 /// known as BCP 47). xml:lang has priority over it.
212 lang: String,
213 /// A cryptographic nonce ("number used once") which can be used by
214 /// Content Security Policy to determine whether or not a given fetch
215 /// will be allowed to proceed.
216 nonce: String,
217 /// A space-separated list of the part names of the element. Part names
218 /// allows CSS to select and style specific elements in a shadow tree
219 /// via the ::part pseudo-element.
220 part: String,
221 /// Assigns a slot in a shadow DOM shadow tree to an element: An element
222 /// with a slot attribute is assigned to the slot created by the
223 /// `<slot>` element whose name attribute's value matches that
224 /// slot attribute's value.
225 slot: String,
226 /// An enumerated attribute defines whether the element may be checked
227 /// for spelling errors. It may have the following values:
228 ///
229 /// - true, which indicates that the element should be, if possible,
230 /// checked for spelling errors;
231 /// - false, which indicates that the element should not be checked for
232 /// spelling errors.
233 spellcheck: String,
234 /// Contains CSS styling declarations to be applied to the element. Note
235 /// that it is recommended for styles to be defined in a separate file
236 /// or files. This attribute and the `<style>` element have mainly the
237 /// purpose of allowing for quick styling, for example for testing
238 /// purposes.
239 style: String,
240 /// An integer attribute indicating if the element can take input focus
241 /// (is focusable), if it should participate to sequential keyboard
242 /// navigation, and if so, at what position. It can take several values:
243 ///
244 /// - a negative value means that the element should be focusable, but
245 /// should not be reachable via sequential keyboard navigation;
246 /// - 0 means that the element should be focusable and reachable via
247 /// sequential keyboard navigation, but its relative order is defined
248 /// by the platform convention;
249 /// - a positive value means that the element should be focusable and
250 /// reachable via sequential keyboard navigation; the order in which
251 /// the elements are focused is the increasing value of the tabindex.
252 /// If several elements share the same tabindex, their relative order
253 /// follows their relative positions in the document.
254 tabindex: i32,
255 /// Contains a text representing advisory information related to the
256 /// element it belongs to. Such information can typically, but not
257 /// necessarily, be presented to the user as a tooltip.
258 title: String,
259 /// An enumerated attribute that is used to specify whether an element's
260 /// attribute values and the values of its Text node children are to be
261 /// translated when the page is localized, or whether to leave them
262 /// unchanged. It can have the following values:
263 ///
264 /// - empty string and yes, which indicates that the element will be
265 /// translated.
266 /// - no, which indicates that the element will not be translated.
267 translate: String,
268 ];
269}
270
271/// Events common to all HTML elements
272pub trait HtmlElementEvents: Element {
273 events!(Self::DomElement {
274 beforeinput: web_sys::InputEvent,
275 change: web_sys::Event,
276 error: web_sys::Event,
277 input: web_sys::InputEvent,
278 drag: web_sys::DragEvent,
279 dragend: web_sys::DragEvent,
280 dragenter: web_sys::DragEvent,
281 dragleave: web_sys::DragEvent,
282 dragover: web_sys::DragEvent,
283 dragstart: web_sys::DragEvent,
284 drop: web_sys::DragEvent,
285 load: web_sys::Event,
286 });
287}
288
289/// Events common to all elements
290pub trait ElementEvents: Element {
291 events!(Self::DomElement {
292 animationcancel: web_sys::AnimationEvent,
293 animationend: web_sys::AnimationEvent,
294 animationiteration: web_sys::AnimationEvent,
295 animationstart: web_sys::AnimationEvent,
296 auxclick: web_sys::MouseEvent,
297 blur: web_sys::FocusEvent,
298 click: web_sys::MouseEvent,
299 compositionend: web_sys::CompositionEvent,
300 compositionstart: web_sys::CompositionEvent,
301 compositionupdate: web_sys::CompositionEvent,
302 contextmenu: web_sys::MouseEvent,
303 dblclick: web_sys::MouseEvent,
304 focusin: web_sys::FocusEvent,
305 focusout: web_sys::FocusEvent,
306 focus: web_sys::FocusEvent,
307 fullscreenchange: web_sys::Event,
308 fullscreenerror: web_sys::Event,
309 gotpointercapture: web_sys::PointerEvent,
310 keydown: web_sys::KeyboardEvent,
311 keyup: web_sys::KeyboardEvent,
312 lostpointercapture: web_sys::PointerEvent,
313 mousedown: web_sys::MouseEvent,
314 mouseenter: web_sys::MouseEvent,
315 mouseleave: web_sys::MouseEvent,
316 mousemove: web_sys::MouseEvent,
317 mouseout: web_sys::MouseEvent,
318 mouseover: web_sys::MouseEvent,
319 mouseup: web_sys::MouseEvent,
320 pointercancel: web_sys::PointerEvent,
321 pointerdown: web_sys::PointerEvent,
322 pointerenter: web_sys::PointerEvent,
323 pointerleave: web_sys::PointerEvent,
324 pointermove: web_sys::PointerEvent,
325 pointerout: web_sys::PointerEvent,
326 pointerover: web_sys::PointerEvent,
327 pointerrawupdate: web_sys::PointerEvent,
328 pointerup: web_sys::PointerEvent,
329 transitioncancel: web_sys::TransitionEvent,
330 transitionend: web_sys::TransitionEvent,
331 transitionrun: web_sys::TransitionEvent,
332 transitionstart: web_sys::TransitionEvent,
333 scroll: web_sys::Event,
334 scrollend: web_sys::Event,
335 securitypolicyviolation: web_sys::SecurityPolicyViolationEvent,
336 touchcancel: web_sys::TouchEvent,
337 touchend: web_sys::TouchEvent,
338 touchmove: web_sys::TouchEvent,
339 touchstart: web_sys::TouchEvent,
340 wheel: web_sys::WheelEvent,
341
342 // These generate a `ClipboardEvent`, but that is currently unstable in `web_sys`.
343 copy: web_sys::Event,
344 cut: web_sys::Event,
345 paste: web_sys::Event,
346 });
347}
348
349macro_rules! aria_attributes {
350 ($($t:tt)*) => {
351 attributes![
352 [
353 attribute_parent = (),
354 attribute_doc_macro = aria_attribute_doc
355 ]
356
357 $($t)*
358 ];
359 };
360}
361
362macro_rules! aria_attribute_doc {
363 ($element:expr, $name:expr) => {
364 concat!(
365 "The ARIA [",
366 $name,
367 "](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/",
368 $name,
369 ") Attribute"
370 )
371 };
372}
373
374/// [ARIA] attributes.
375///
376/// [ARIA]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA
377pub trait AriaElement: Element {
378 attributes
380 /// attribute
381 role: String,
382 ];
383 aria_attributes![
384 /// The aria-activedescendant attribute identifies the currently active
385 /// element when focus is on a composite widget, combobox, textbox,
386 /// group, or application.
387 aria_activedescendant: String,
388 /// In ARIA live regions, the global aria-atomic attribute indicates
389 /// whether assistive technologies such as a screen reader will present
390 /// all, or only parts of, the changed region based on the change
391 /// notifications defined by the aria-relevant attribute.
392 aria_atomic: String,
393 /// The aria-autocomplete attribute indicates whether inputting text
394 /// could trigger display of one or more predictions of the user's
395 /// intended value for a combobox, searchbox, or textbox and specifies
396 /// how predictions will be presented if they are made.
397 aria_autocomplete: String,
398 /// The global aria-braillelabel property defines a string value that
399 /// labels the current element, which is intended to be converted into
400 /// Braille.
401 aria_braillelabel: String,
402 /// The global aria-brailleroledescription attribute defines a
403 /// human-readable, author-localized abbreviated description for the
404 /// role of an element intended to be converted into Braille.
405 aria_brailleroledescription: String,
406 /// Used in ARIA live regions, the global aria-busy state indicates an
407 /// element is being modified and that assistive technologies may want
408 /// to wait until the changes are complete before informing the user
409 /// about the update.
410 aria_busy: String,
411 /// The aria-checked attribute indicates the current "checked" state of
412 /// checkboxes, radio buttons, and other widgets.
413 aria_checked: String,
414 /// The aria-colcount attribute defines the total number of columns in a
415 /// table, grid, or treegrid when not all columns are present in the
416 /// DOM.
417 aria_colcount: i64,
418 /// The aria-colindex attribute defines an element's column index or
419 /// position with respect to the total number of columns within a table,
420 /// grid, or treegrid.
421 aria_colindex: u64,
422 /// The aria-colindextext attribute defines a human readable text
423 /// alternative of the numeric aria-colindex.
424 aria_colindextext: String,
425 /// The aria-colspan attribute defines the number of columns spanned by
426 /// a cell or gridcell within a table, grid, or treegrid.
427 aria_colspan: u64,
428 /// The global aria-controls property identifies the element (or
429 /// elements) whose contents or presence are controlled by the element
430 /// on which this attribute is set.
431 aria_controls: String,
432 /// A non-null aria-current state on an element indicates that this
433 /// element represents the current item within a container or set of
434 /// related elements.
435 aria_current: String,
436 /// The global aria-describedby attribute identifies the element (or
437 /// elements) that describes the element on which the attribute is set.
438 aria_describedby: String,
439 /// The global aria-description attribute defines a string value that
440 /// describes or annotates the current element.
441 aria_description: String,
442 /// The global aria-details attribute identifies the element (or
443 /// elements) that provide additional information related to the object.
444 aria_details: String,
445 /// The aria-disabled state indicates that the element is perceivable
446 /// but disabled, so it is not editable or otherwise operable.
447 aria_disabled: String,
448 /// The aria-errormessage attribute on an object identifies the element
449 /// that provides an error message for that object.
450 aria_errormessage: String,
451 /// The aria-expanded attribute is set on an element to indicate if a
452 /// control is expanded or collapsed, and whether or not its child
453 /// elements are displayed or hidden.
454 aria_expanded: String,
455 /// The global aria-flowto attribute identifies the next element (or
456 /// elements) in an alternate reading order of content. This allows
457 /// assistive technology to override the general default of reading in
458 /// document source order at the user's discretion.
459 aria_flowto: String,
460 /// The aria-haspopup attribute indicates the availability and type of
461 /// interactive popup element that can be triggered by the element on
462 /// which the attribute is set.
463 aria_haspopup: String,
464 /// The aria-hidden state indicates whether the element is exposed to an
465 /// accessibility API.
466 aria_hidden: String,
467 /// The aria-invalid state indicates the entered value does not conform
468 /// to the format expected by the application.
469 aria_invalid: String,
470 /// The global aria-keyshortcuts attribute indicates keyboard shortcuts
471 /// that an author has implemented to activate or give focus to an
472 /// element.
473 aria_keyshortcuts: String,
474 /// The aria-label attribute defines a string value that labels an
475 /// interactive element.
476 aria_label: String,
477 /// The aria-labelledby attribute identifies the element (or elements)
478 /// that labels the element it is applied to.
479 aria_labelledby: String,
480 /// The aria-level attribute defines the hierarchical level of an
481 /// element within a structure.
482 aria_level: u64,
483 /// The global aria-live attribute indicates that an element will be
484 /// updated, and describes the types of updates the user agents,
485 /// assistive technologies, and user can expect from the live region.
486 aria_live: String,
487 /// The aria-modal attribute indicates whether an element is modal when
488 /// displayed.
489 aria_modal: String,
490 /// The aria-multiline attribute indicates whether a textbox accepts
491 /// multiple lines of input or only a single line.
492 aria_multiline: String,
493 /// The aria-multiselectable attribute indicates that the user may
494 /// select more than one item from the current selectable descendants.
495 aria_multiselectable: String,
496 /// The aria-orientation attribute indicates whether the element's
497 /// orientation is horizontal, vertical, or unknown/ambiguous.
498 aria_orientation: String,
499 /// The aria-owns attribute identifies an element (or elements) in order
500 /// to define a visual, functional, or contextual relationship between a
501 /// parent and its child elements when the DOM hierarchy cannot be used
502 /// to represent the relationship.
503 aria_owns: String,
504 /// The aria-placeholder attribute defines a short hint (a word or short
505 /// phrase) intended to help the user with data entry when a form
506 /// control has no value. The hint can be a sample value or a brief
507 /// description of the expected format.
508 aria_placeholder: String,
509 /// The aria-posinset attribute defines an element's number or position
510 /// in the current set of listitems or treeitems when not all items are
511 /// present in the DOM.
512 aria_posinset: u64,
513 /// The aria-pressed attribute indicates the current "pressed" state of
514 /// a toggle button.
515 aria_pressed: String,
516 /// The aria-readonly attribute indicates that the element is not
517 /// editable, but is otherwise operable.
518 aria_readonly: String,
519 /// Used in ARIA live regions, the global aria-relevant attribute
520 /// indicates what notifications the user agent will trigger when the
521 /// accessibility tree within a live region is modified.
522 aria_relevant: String,
523 /// The aria-required attribute indicates that user input is required on
524 /// the element before a form may be submitted.
525 aria_required: String,
526 /// The aria-roledescription attribute defines a human-readable,
527 /// author-localized description for the role of an element.
528 aria_roledescription: String,
529 /// The aria-rowcount attribute defines the total number of rows in a
530 /// table, grid, or treegrid.
531 aria_rowcount: i64,
532 /// The aria-rowindex attribute defines an element's position with
533 /// respect to the total number of rows within a table, grid, or
534 /// treegrid.
535 aria_rowindex: u64,
536 /// The aria-rowindextext attribute defines a human-readable text
537 /// alternative of aria-rowindex.
538 aria_rowindextext: String,
539 /// The aria-rowspan attribute defines the number of rows spanned by a
540 /// cell or gridcell within a table, grid, or treegrid.
541 aria_rowspan: u64,
542 /// The aria-selected attribute indicates the current "selected" state
543 /// of various widgets.
544 aria_selected: String,
545 /// The aria-setsize attribute defines the number of items in the
546 /// current set of listitems or treeitems when not all items in the set
547 /// are present in the DOM.
548 aria_setsize: i64,
549 /// The aria-sort attribute indicates if items in a table or grid are
550 /// sorted in ascending or descending order.
551 aria_sort: String,
552 /// The aria-valuemax attribute defines the maximum allowed value for a
553 /// range widget.
554 aria_valuemax: f64,
555 /// The aria-valuemin attribute defines the minimum allowed value for a
556 /// range widget.
557 aria_valuemin: f64,
558 /// The aria-valuenow attribute defines the current value for a range
559 /// widget.
560 aria_valuenow: f64,
561 /// The aria-valuetext attribute defines the human readable text
562 /// alternative of aria-valuenow for a range widget.
563 aria_valuetext: String,
564 ];
565}