Skip to Content
ConceptsEssential Concepts

How DoenetML works

Definitions: Components, Attributes, and Properties

DoenetML is a markup language much like HTML. When creating content in DoenetML, you are essentially working with 3 types of data objects:

  • Components - also called “tags” informally, describe the type of content that is being defined or rendered. Typically, a component will consist of an opening tag <componentName> and a closing tag </componentName>, with content, content specifications, or other components occuring between these two tags. Some components, if they do not require additional information, may be self-closing, <componentName/>.

  • Attributes - provide information necessary to define the component’s desired behavior within the opening tag. The syntax for specifying an attribute is: <componentName attr="value">.

  • Properties (or Props) - props are stored information relating to a component that may be accessed by referencing the component by name, followed by the name of the property.

Example: Illustration of components, attributes and properties

The available attributes and properties vary by component. See the Component Examples section for a full listing for each.

Component Types

The components in DoeneML can be categorized into several functional types that characterize their most common use-case and functionality. The system presented here is not a formal, programmatic characterization; it is intended to mainly help authors of DoenetML find and select useful components when building activities, and to make learning components easier.

To see a list of components organized by type, see the Index by Component Type page.

The different types are:

Type of ComponentDescription
Paragraph Markupused within a paragraph, or <p> tag to change the way text is rendered
Sectionalused to structure content on the page; may have auto-numbering
Inputused to gather user-input, such as text-boxes, multiple-choice selections, or checkboxes
Graphicalused to render interactive elements on a graph
Display Mathused to render LaTeX; does not invoke the CAS
Mathused to define mathematical content; can be symbolic or numerical
Math Operatorused to perform mathematical operations
General Operatorused to perform operations on math and non-math components
Logicused to define boolean conditions
Evaluationused with answer validation and awarding of credit
Textany component that uses text strings outside the context of a paragraph
Subject-specificcomponents that are unique to a specific STEM field, such as chemistry or physics

Some components may belong to more than one functional type, such as a <sequence>, which can generate either a numerical or a text sequence, or a <mathInput> which collects student’s mathematical responses and also stores the value as a Math Component for use in computations by the CAS.

The Computer Algebra System (CAS)

DoenetML is linked to a CAS which performs the basic computations necessary for the behavior of mathematical and graphical components, as well as answer-checking.

All Math Components and Graphical Components have access to the CAS, which can be used when evaluating or responding to user interactions with these components. For example, when a user drags a <line>, dilates a <circle>, or updates the coefficient in an equation via a <mathInput>, the CAS instantaneously updates all of the stored property data relating to that component.

Mathematical Display components, by contrast, do not access the CAS.

Basic Language syntax

Components can communicate information between one another by means of references. To create a reference, attach a name attribute to a defined component following the DoenetML naming convention.

Naming conventions

DoenetML naming convention:

  • Can only contain numbers, letters, and underscores
  • Cannot start with an underscore or a number
  • Is case-sensitive

When you need to access the value of the named component or one of its stored properties, use the notation $componentName to create a reference to the component itself, and use the notation $componentName.propertyName to create a reference to one of its properties.

Example: Referencing the stored value of a named component

Sizes: width and height

Several components let you set their rendered size with a width attribute and, where a component has a height of its own to set, a height attribute: <textInput/>, <codeEditor/>, <spreadsheet/>, <tabular/>, <slider/>, <sideBySide/>, <sbsGroup/>, <graph/>, <image/>, and <video/>. They all read the value the same way, with two exceptions noted at the end of this section.

A bare number means pixels. width="600" and width="600px" are the same size. You can also write the size in physical units:

ValueMeaning
600600 pixels
600px600 pixels; the unit may also be spelled pixel or pixels, with or without a space before it
6in6 inches, or 576 pixels; also spelled inch or inches
450pt450 points, or 600 pixels
15cm15 centimeters, or about 567 pixels; also spelled centimeter or centimeters
150mm150 millimeters, the same size; also spelled millimeter or millimeters

A height takes one of these sizes. A width takes them too, and may instead be written as a percentage.

Relative sizes

A percentage is measured against the width available to the component — the width of the page column it sits in, or of whatever encloses it. It is the one form that keeps a component in proportion when the reader’s window is narrow, so reach for it when a fixed number of pixels would be too wide on a phone:

An expanded <textInput/> takes a percentage the same way, and is 100% wide unless you say otherwise. A word-sized input is the exception: it keeps whatever width it is given, and the line it sits in closes around it, so a percentage there would be a share of a box whose own width depends on the input. Give a word-sized input an absolute width.

em is not a font-relative size here. Unlike in CSS, DoenetML reads em as a multiple of 100%, so width="2em" means 200% and width="1em" means 100%. Write the percentage you mean instead.

A unit DoenetML does not recognize is quietly read as pixels: width="300 furlongs" renders 300 pixels wide. A value that does not begin with a number at all — width="wide" — yields no size. That is not the same as leaving the attribute off: the component does not fall back to its default width, it is laid out with no width of its own. Delete the attribute rather than give it a value DoenetML cannot read.

Sizes that snap to a preset

<graph/>, <image/>, and <video/> are the first exception. Their width does not set an exact width; it picks the nearest of five named sizes, which you can also set directly with their size attribute:

sizeWidth
tiny70 pixels
small255 pixels
medium425 pixels
large595 pixels
full850 pixels

So width="400px" and width="50%" both render one of these components at medium, 425 pixels wide. Reading back the component’s size property tells you which preset a width landed on.

A percentage means something different here than it does elsewhere. It is a share of the 850 pixels of the full preset — the widest any component may be — rather than of the space around the component, so width="50%" picks medium however narrow the surrounding column happens to be.

An <image/> drawn on a <graph/> is the exception to the exception: there its width is used as given, measured against the graph’s own scale rather than snapped to a preset.

Sizes that must be relative

<sideBySide/> and <sbsGroup/> are the second exception. They divide a row into shares, so their width, widths, and margins are read as percentages only. An absolute size there raises a warning and is treated as the percentage of the same number, which is rarely what you meant — write width="50%", not width="50".

Last updated on