.. _typeset-math: ########################## MathJax in Dynamic Content ########################## When MathJax is initially loaded, it will typeset any math that is available in the page. For static pages, that is all that you will need to do to make your mathematics appear and be accessible. Many pages, however, load or create content dynamically, and if that new material contains mathematics, MathJax will need to be told to typeset that new mathematics, as that is not done automatically by MathJax. The following sections show how this can be done within the :ref:`mathjax-components` framework using the commands that are part of the :data:`MathJax` global variable. For node applications or custom builds of MathJax that don't use MathJax Components, you would need to use the lower-level direct calls to the MathJax :data:`MathDocument` methods that correspond to those commands. .. _dynamic-new-content: Handling New Content ==================== If you are writing a dynamic web page where content containing mathematics may appear after MathJax has already typeset the rest of the page, then you will need to tell MathJax to look for mathematics in the page again when that new content is produced. To do that, you need to use one of the :js:meth:`MathJax.typeset()` or :js:meth:`MathJax.typesetPromise()` functions. These cause MathJax to look for unprocessed mathematics on the page and typeset it, leaving unchanged any math that has already been typeset. The first of these runs synchronously, but if the mathematics on the page uses ``\require`` or causes an extension to be auto-loaded (via the :ref:`tex-autoload` component), or needs characters from a region of the font that hasn't already been loaded, this will cause the :js:meth:`MathJax.typeset()` call to fail. In this case, you should use :js:meth:`MathJax.typesetPromise()` instead. This returns a promise that is resolves when the typesetting is complete. See the :ref:`typeset-async` section for more details. .. note:: The :js:meth:`MathJax.typeset()` command corresponds to .. code-block:: javascript (elements = null) => { const doc = MathJax.startup.document; doc.options.elements = elements; doc.reset(); doc.render(); } and :js:meth:`MathJax.typesetPromise()` corresponds to .. code-block:: javascript (elements = null) => { const doc = MathJax.startup.document; return doc.whenReady(async () => { doc.options.elements = elements; doc.reset(); await doc.renderPromise(); }); } Those not using MathJax Components can use these definitions, where ``const doc = ...`` is replaced by your own :data:`MathDocument` object created by :js:meth:`mathjax.document()`. .. _dynamic-changed-content: Handling Content that Changes ============================= Some web pages replace old content with new content in some circumstances. For example, a "book reader" may load individual pages to be displayed in its main content area, with each new page replacing the previously viewed one, or a page that allows users to enter content may include an editor with a preview that updates as the user types new content. When the changing content includes typeset mathematics, special care must be taken to inform MathJax that previously typeset mathematics is being removed before doing so. This is because MathJax keeps track of the expressions that it typesets so that they can be updated if changes are made to the menu settings. For example, if the renderer is changed, MathJax needs to go back and re-render all the expressions, so it needs to know where they are in the page. Information about the mathematics that MathJax has typeset is stored in a list of :data:`MathItem` objects that is part of the :data:`MathDocument` maintained by MathJax. If content containing typeset mathematics is removed from the page, the corresponding :data:`MathItem` objects need to be removed from that list, otherwise MathJax will think that math is still in the page, which can lead to problems if MathJax tries to re-render those items. It also means that the list can grow unexpectedly large, and that the old typeset expressions are not freed from memory, causing MathJax's memory usage to grow. In a situation like an editor with preview, where the content is updated for each keystroke, that can lead to a rapid growth in memory and a corresponding decrease in performance over time. To deal with changing content, MathJax provides a function that tells it to forget about math that it has previously typeset: .. js:function:: MathJax.typesetClear(elements) :param HTMLElement[] elements: An optional array of HTML elements whose typeset math is to be forgotten. If not given, all math items are forgotten (i.e., the entire list of items is removed). If you are removing a portion of your document that may include typeset mathematics, you should call this function **before** removing the content from the DOM so that MathJax can determine which expressions it contains and remove them from its internal list of expressions. If you fail to do this, MathJax's expression list will contain orphan expressions that are no longer part of the DOM. .. note:: The :js:meth:`MathJax.typesetClear()` method corresponds to .. code-block:: js (elements = null) => { const doc = MathJax.startup.document; if (elements) { doc.clearMathItemsWithin(elements); } else { doc.clear(); } } Those not using MathJax Components can use these definitions, where ``const doc = ...`` is replaced by your own :data:`MathDocument` object created by :js:meth:`mathjax.document()`. Once you have called :js:meth:`MathJax.typesetClear()`, you can remove the elements that you passed it or clear their contents and replace them with other content. Then call :js:meth:`MathJax.typesetPromise()` to typeset that new content. If your input format is LaTeX, then the new content will have access to any macro definitions or labels that were defined in any previous content, and automatic equation numbering will continue with the next number, even if you remove equations with earlier numbers. In an editor setting, where the same content is typeset over and over, this can lead to errors about multiply-defined labels, incorrect application of macros before they are supposed to be defined, and equation numbers going up on each re-rendering. To overcome these problems, you can use the :js:meth:`MathJax.texReset()` method to remove any previously-defined labels, and optionally set the automatic equation numbering starting value. .. note:: The :js:meth:`MathJax.texReset()` command corresponds to .. code-block:: javascript (...args) => { const jax = MathJax.startup.document.inputJax.tex; jax.reset(...args); } Those not using MathJax Components can use these definitions, where ``const jax = ...`` is replaced by your TeX input jax instance. To reset macro definitions, you can use the :ref:`tex-begingroup` extension to isolate the definitions used for one typesetting pass from the following ones. Its ``\begingroupSandbox`` is one way to do that, which you can process using .. code-block:: js MathJax.tex2mml('\\begingroupSandbox'); These techniques are illustrated in the example in the next section. .. _dynamic-preview-example: Editor Preview Example ====================== The following code combines the mechanisms discussed above into an example that implements a basic editor with a preview that is updated on every change the the input area. This example uses the HTML that the user enters, updates an output area using that, and calls MathJax to process the expressions it contains. Of course, in practice, you would want to sanitize the user input to prevent the user from entering malicious code, so this is just the bare-bones version meant to highlight how to handle the MathJax update portion of the editor tasks. The details are discussed after the code listing below. .. code-block:: html :linenos: