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![
379        /// The ARIA [role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)
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}