Constructor
new Atom(element, editor)
Construct a new instance of this class corresponding to the atom
represented by the given HTMLElement
. Recall that the purpose of this
class, as documented above, is to provide an API for consistent and
convenient use of atoms, an API that is not part of the HTMLElement
API. Thus to use that API, you use this constructor and then call
functions on the resulting object. The intent is for such instances to
be ephemeral, in the sense that you can create one, use it, and let it be
garbage collected immediately thereafter, with little performance cost.
Parameters
-
element
HTMLElement
the element in the editor (a span or div) representing the atom
-
editor
tinymce.Editor
the editor in which the element sits
Source
Methods
applyValidationMessage(message)
This function inspects the given Message, which the caller wants applied to this Atom. It determines which of its feedback contents, if any, should be displayed to the user. It then makes a call to setValidationResult() to display that feedback.
The default implementation is to just extract the first piece of feedback from the message other than a message about an undeclared variable and use it, or if there is no such feedback in the message, erase the feedback shown on this Atom. However, subclasses can override this default behavior if they have specific types of feedback that they want to prioritize, or they need to combine multiple types of feedback.
Parameters
-
message
Message
the message whose validation data should be used to decorate this Atom
Source
contextMenu(forThis)
The default context menu for an atom is just the context menu for its parent atom, if any, or the empty array otherwise. This makes it easy to include the context menu for all ancestor atoms in any atom, by just starting with the context menu of the superclass and then adding items.
Parameters
-
forThis
Atom
the atom that received the right-click action that led to the creation of the context menu
Source
dataChanged()
This function is a handler for whenever the metadata stored in this atom changes. Its default implementation is to do nothing, but having it here allows the validation module to replace this handler with one that clears all validation feedback. We do it this way, rather than importing the validation module and calling its "clear" function ourselves, because it prevents a circular dependency.
See
- wasDeleted()
Source
edit() → {Promise}
This is a placeholder implementation of this method, to be sure that all Atom instances have one. In subclasses, the function should pop up an editor for the user to edit this atom, and return a promise that resolves to true if the user saves their edits, and false if they cancel. The user's edits should already be saved into the atom when the promise resolves to true. This placeholder implementation returns a promise that false immediately, as if the user canceled their edits instantaneously.
Returns
-
Promise
a promise that resolves to
false
Source
editThenInsert()
The standard way to insert a new atom into the editor is to create it off screen, open up an editing dialog for that atom, and then if the user saves their edits, insert the new atom into the document, in the final state that represents the user's edits. If, however, the user cancels their edit of the atom, don't insert anything into the document.
This function does exactly that, when called on an offscreen atom, passing the editor into which to insert the atom as the first parameter.
See
- edit()
- editThenInsert()
Source
fillChild(type, html)
Fill the child of the specified type with the given HTML content. If the child does not yet exist, create it before populating it. See the documentation for getChild() for an explanation of the children of atoms.
Parameters
-
type
string
which type of child to write to; see the documentation for getChild() for a list of the valid children types
-
html
string
the HTML code to use to fill the child
Source
getChild(type, createIfNeeded) → {HTMLElement}
An atom has the following three or four internal parts, called children. If the atom is inline (a span) then each of the children is represented as an inner span, but if the atom is a block (a div) then each of the children is an inner div.
- The "metadata" child, which exists only in block-type atoms, and can contain arbitrarily large HTML metadata, none of which is displayed in the document for the user to see. Clients should not read from or write to this HTML metadata storage directly, but should instead use the functions in this class designed for that purpose, including getHTMLMetadata() and setHTMLMetadata(). The reason that this exists only in block-type atoms is because one cannot put arbitrary HTML inside a span, as one can with a div.
- The "prefix" child, which is the first child that is visible to the user in the document. This may be omitted or empty, but in those situations where the atom should have some decoration on its left side (for inline atoms) or its top (for block atoms), such content can be placed in the prefix. The client rarely needs to write to the prefix directly, but can instead use the fillChild() function to do so. You can use this function to read from the prefix when needed.
- The "body" child, which is where the main content of the atom should go. For example, if the atom represents a mathematical equation, the typeset version of that equation can go here. Again, to specify the body content, use fillChild().
- The "suffix" child, which functions just like the prefix, except appears at the end (right side for inline atoms, bottom for block atoms). Again, to specify the suffix content, use fillChild().
When you call this function, both parameters are optional. If you do not
specify the type of child, it defaults to the body, and if the child you
request does not exist, it defaults to creating it for you. (In a brand
new atom, there are no children; it is empty.) If you do not wish the
child to be created, but rather receive undefined
as the result if it
does not exist, set the second parameter to false
.
Parameters
-
type
string
bodywhich type of child to fetch, must be one of
"metadata"
,"prefix"
,"body"
, or"suffix"
(default is"body"
) -
createIfNeeded
boolean
truewhether to create the child in question if it does not already exist (default is
true
)
Returns
-
HTMLElement
the child of the given type inside this atom
Source
getHTML() → {string}
Get the HTML representation of this atom, as it currently sits in the
document. There is no corresponding setHTML()
function; instead, see
fillChild().
See
- getHTML()
Returns
-
string
the HTML representation of this atom
Source
getHTMLMetadata(key) → {HTMLDivElement}
Look up an HTML metadata entry in this atom using the given key. In addition to the JSONable metadata that can be stored in any atom (as documented in getMetadata()), you can also store arbitrarily large amounts of HTML in block-type atoms (not inline ones). This is useful, for example, when storing an entire dependency's HTML inside the atom that has imported it; the data can be stored as DOM nodes rather than as a JSON-encoded HTML string. This makes it easier to use when doing computations that depend on the meaning of the dependency's content.
This type of metadata is stored inside the "metadata"
child of the
block-type atom, as documented here.
The return value for this function will be an HTMLDivElement
that sits
inside that "metadata"
child, and serves as a wrapper containing any
number of HTML elements (or any large amount of text). While the return
value is a single element, it is a wrapper that should be ignored,
because its child node list is the actual value of the metadata that was
looked up.
Parameters
-
key
string
the key whose HTML should be looked up
Returns
-
HTMLDivElement
the element wrapping the corresponding value
Source
getHTMLMetadataKeys() → {Array.<string>}
Look up the keys for all HTML metadata entries stored in this atom. For information on the difference between basic atom metadata and HTML metadata, see the documentation here.
Returns
-
Array.<string>
all keys under which HTML metadata has been stored in this atom
Source
getMetadata(key) → {any}
Look up a metadata entry in this atom using the given key. Atoms can contain metadata mapping any string key to any JSONable value. Thus this function will return a JSONable object, as extracted from the given key, if that key indeed appears in this atom's metadata.
This type of metadata is stored in the dataset
property of the
HTMLElement
representing the atom. This is a natural way to store
small amounts of data about the atom. For larger amounts of data, you
may wish to use getHTMLMetadata() instead.
Parameters
-
key
string
the key whose value should be looked up
Returns
-
any
the data associated with the given key, or undefined if the key is not in the metadata
Source
getMetadataKeys() → {Array.<string>}
Look up the keys for all metadata entries stored in this atom. Atoms can contain metadata mapping any string key to any JSONable value. This function returns only the keys, as an array.
Returns
-
Array.<string>
all keys under which metadata has been stored in this atom
Source
getValidationResults()
Return the array of all validation results in this Atom.
Source
isEditable()
Atoms are always editable, unless they sit inside some DOM node that is
marked as contenteditable=false
. This function checks to see if that
is the case, and returns true iff no ancestor DOM node has that property.
Source
parent() → nullable{Atom}
If this atom is contained inside another atom, then the innermost such atom is this one's "parent." This function returns that parent, if any, and null otherwise.
Returns
-
Atom
the Atom that is the parent of this Atom, if any
Source
removeChild(type)
Remove the child with the specified type (or do nothing if there is no such child). See the documentation for getChild() for an explanation of the children of atoms.
Parameters
-
type
string
which type of child to write to; see the documentation for getChild() for a list of the valid children types
Source
removeHTMLMetadata(key)
Remove an HTML metadata entry from this atom, with the given key.
Parameters
-
key
string
the key that (together with its value) should be removed
Source
removeMetadata(key)
Remove a metadata entry from this atom, with the given key.
Parameters
-
key
string
the key that (together with its value) should be removed
Source
setHTMLMetadata(key, value)
Store an HTML metadata entry in this atom under the given key. Block-type atoms can contain metadata mapping any string key to any amount of HTML content, as documented here. This function stores a new entry in that metadata storage area.
Note that only block-type atoms can contain HTML metadata, and so calling this function on an inline atom will throw an error.
Any HTML element passed as the value will not be used directly, but will
be copied (i.e., its HTML code will be written to the .innerHTML
property of the appropriate metadata element), in case the element in
question is not from the same document. The value may instead be the
HTML code itself, as a string.
Parameters
-
key
string
the key under which to store the value
-
value
HTMLElement
|string
the value to store, either as an HTMLElement or a string
Source
setHoverText(textnullable)
Set (or clear) the hover text on this atom. Hover text is what's shown in a small popup when the user hovers over the atom in the editor.
Parameters
-
text
string
<nullable>
the text to set as the hover text for this atom's HTMLElement, or
null
to remove the hover text
Source
setMetadata(key, value)
Store a metadata entry in this atom under the given key. Atoms can contain metadata mapping any string key to any JSONable value, so you should provide a value that is amenable to JSON encoding. It will be stored using its JSON encoding, as a string.
If the caller omits the value
parameter, or sets it to undefined, this
function does nothing.
Parameters
-
key
string
the key under which to store the value
-
value
any
the value to store
Source
setValidationResult(resultnullable, reasonnullable)
Set the suffix of the atom to reflect its validation result.
The first argument must be one of "valid"
, "invalid"
, "error"
, or
"indeterminate"
. No error is thrown if you use another value, but it
will not display any meaningful feedback icon. To clear all validation
feedback, omit both arguments, or call setValidationResult(null)
. The
meanings of these indicators are as follows.
"valid"
: the atom represents correct mathematical work"invalid"
: the atom represents incorrect mathematical work"indeterminate"
: the atom cannot be clearly classified as valid or invalid (e.g., the user has provided something vague, and their settings specify that such things should not be aggressively marked wrong, but just indeterminate, to request more specificity)"error"
: the software encountered an internal error while attempting to validate the atom. (Obviously this is to be avoided! It is available to use if an internal error occurs, so that the user gets truthful feedback in such a case, and can report the bug so that we can set about trying to fix it. But of course we strive to write software does not encounter errors, and thus in which this type of feedback is never actually seen by a user.)
The second argument should be the text to be shown when the user hovers
their mouse over the atom. You can omit this if you do not want any
such text, but it is recommended to always have such text, for the user's
benefit. Note that browsers do not support HTML tags in such hover text
panels, but they do support newline characters ("\n"
).
Parameters
-
result
string
<nullable>
the validation result, one of
"valid"
,"invalid"
,"error"
, or"indeterminate"
; can be omitted in order to clear all validation feedback -
reason
string
<nullable>
the reason for the validation result, as text to be displayed when the user hovers their mouse over the atom
Source
toLCs() → {Array.<LogicConcept>}
This is a placeholder implementation of this method, to be sure that all Atom instances have one. In subclasses, the function should return an array of LogicConcepts that represent the meaning of this atom. If the atom has no meaning in terms of LogicConcepts, simply return an empty array. That is the default implementation.
Returns
-
Array.<LogicConcept>
an empty array of LogicConcepts, in this default implementation
Source
toLatex() → {string}
All atoms must be able to represent themselves in LaTeX form, so that the
document (or a portion of it) can be exporeted for use in a LaTeX editor,
such as Overleaf. The default implementation, defined here in the Atom
class, is to return a string of the form "(Lurch X)"
, where X
is the
type of the atom. For example, "(Lurch expression)"
. Subclasses are
likely to override this with something more suitable and useful in a
LaTeX document.
Returns
-
string
default LaTeX representation of the atom
Source
update()
This is a placeholder implementation of this method, to be sure that all Atom instances have one. In subclasses, the function should update the visible representation of the atom in the document based on the attributes stored in its metadata. The default implementation does nothing.
Source
wasDeleted()
This function is a handler for whenever an atom has just been deleted from the document. Its default implementation is to do nothing, but having it here allows the validation module to replace this handler with one that clears all validation feedback. We do it this way, rather than importing the validation module and calling its "clear" function ourselves, because it prevents a circular dependency.
See
- dataChanged()
Source
allElementsIn(editor) → {Array.<HTMLElement>}
Find all elements in the given TinyMCE editor that represent atoms, and return each one in the order they appear in the document.
Parameters
-
editor
tinymce.Editor
the editor in which to search
See
Returns
-
Array.<HTMLElement>
the array of atom elements in the editor's document
Source
allIn(editor) → {Array.<Atom>}
Find all elements in the given TinyMCE editor that represent atoms, and return each one, transformed into an instance of the Atom class. They are returned in the order they appear in the document.
Parameters
-
editor
tinymce.Editor
the editor in which to search
See
Returns
-
Array.<Atom>
the array of atom in the editor's document
Source
create(editor, tagName, content, metadata) → {Atom}
Create a new atom element, as in createElement(), then fill its body with the given content, optionally set one or more metadata key-value pairs, and return an Atom instance corresponding to the new element. Note that this does not insert the element anywhere into the editor.
Parameters
-
editor
tinymce.Editor
the TinyMCE editor in which to create the element
-
tagName
string
the tag to use,
"span"
for inline atoms or"div"
for block-type atoms (which is the default) -
content
string
the HTML code to use for filling the body of the newly created atom
-
metadata
Object
a dictionary of key-value pairs to store in the metadata of the newly created atom (defaults to the empty object
{ }
, meaning not to add any metadata)
Returns
-
Atom
the Atom instance corresponding to the newly created atom element
Source
createElement(editor, tagName) → {HTMLElement}
Create an HTMLElement that can be placed into the given editor
and that
represents an inline or block-type atom, as specified by the second
parameter. The element will be given an HTML/CSS class that marks it as
representing an atom, and will be marked uneditable so that TinyMCE will
not allow the user to alter it directly.
Parameters
-
editor
tinymce.Editor
the TinyMCE editor in which to create the element
-
tagName
string
divthe tag to use,
"span"
for inline atoms or"div"
for block-type atoms (which is the default)
Returns
-
HTMLElement
the element constructed
Source
findAbove(node, editor) → nullable{Atom}
When a mouse event takes place in the document, it is useful to be able to check whether it happened inside an element representing an atom. So this function can take any DOM node and walk up its ancestor chain and find whether any element in that chain represents an atom. If so, it returns the corresponding Atom instance. If not, it returns null.
Parameters
-
node
Node
the DOM node from which to begin searching
-
editor
tinymce.Editor
the editor in which the node sits
See
Returns
-
Atom
the nearest Atom enclosing the given
node
Source
from(element, editor) → {Atom}
Instead of the Atom constructor, use this function to convert an element in the document into a functioning Atom instance. The reason you should use this function is because the Atom constructor always creates an Atom instance, but this function may create an instance of an Atom subclass, if that's what the element represents. Thus the resulting object will have more specialized functionality suitable to the type of atom in question. This behavior is powered by the registration of Atom subclasses using registerSubclass().
Parameters
-
element
HTMLElement
an element that has passed the check in isAtomElement()
-
editor
tinymce.Editor
the editor in which the element sits
Returns
-
Atom
the atom represented by the element
Source
isAtomElement(element) → {boolean}
One can construct an instance of the Atom class to interface with an element in the editor only if that element actually represents an atom, as defined in the documentation for the Atoms module. This function checks to see if the element in question does. To create elements that do represent atoms, see createElement().
Parameters
-
element
HTMLElement
the element to check
Returns
-
boolean
whether the element represents an atom
Source
newBlock(editor, content, metadata) → {Atom}
A convenience function that calls create() for you, but uses the tag "div"
to make an inline element.
This makes the client's code more clear, because it specifies that we are
creating a new block-type atom.
Parameters
-
editor
tinymce.Editor
same as in create()
-
content
string
same as in create()
-
metadata
Object
same as in create()
Returns
-
Atom
same as in create()
Source
newInline(editor, content, metadata) → {Atom}
A convenience function that calls create() for you, but uses the tag "span"
to make an inline element.
This makes the client's code more clear, because it specifies that we are
creating a new inline atom.
Parameters
-
editor
tinymce.Editor
same as in create()
-
content
string
same as in create()
-
metadata
Object
same as in create()
Returns
-
Atom
same as in create()
Source
registerSubclass(name, subclass)
This class tracks its collection of subclasses so that elements in the editor can have an appropriate Atom subclass wrapper created around them as needed, for custom event handling. To register a subclass, call this function. To create an atom that has the right subclass, see from().
Example:
class Example extends Atom { ... }
Atom.registerSubclass( 'Example', Example )
Parameters
-
name
string
the name of the subclass to register
-
subclass
Object
the subclass itself
Source
simplifiedHTML() → {string}
When embedding a copy of the Lurch app in a larger page, users will want to write simple HTML describing a Lurch document, then have a script create a copy of the Lurch app and put that document into it. This function can convert any HTML, including HTML that has atom elements in it, into that simplified HTML that is more human-readable, yet still describes a Lurch document.
Returns
-
string
the representation of the atom as a
lurch
element
Source
unsimplifyDOM(node, editor)
Traverse a DOM tree and convert any simplified HTML elements in it into
HTML elements that represent atoms (or shells). For example, an HTML
element of the form <latex>...</latex>
will be replaced with the full
HTML code for a ExpositorMath atom as it sits in a Lurch
application's document.
Parameters
-
node
Node
the DOM node to use as the root of the traversal; it is modified in-place
-
editor
tinymce.Editor
the editor in which the modified DOM will eventually be placed or copied